文字列を浮動小数点に変換したいと思っています。
StrToFloat()を用いたのですが、有効数値がケタ落ちしてしまいました。
そこで、次のように関数を定義して実行したところ、やはり戻り値の値がケタ落ちしました。
long double StrToValue(AnsiString str)
{
・・・・・
return value;
}
具体的にはlong doubleの有効数値がdouble型の有効数値にまで落ちてしまっています。
次にポインタを使い、次のように変更したのですが、結果は同じでした。
void StrToValue(AnsiString str, long double *value)
{
・・・・・
*value=・・・;
・・・・・
}
どなたか、この解決方法と、できれば理由を教えてください。
なお使用した言語は、C++Builder 5
環境はWindows 98 です。
No.3ベストアンサー
- 回答日時:
> そこで、デバッガを使って調べたところ、StrToValue(AnsiString str)のreturn直前では、
> result=-1.55519334183474013
> となっており、str を正確に数値に変換していました。
ということであれば、可能ならば、関数の宣言から _fastcall を外すと、
回避できるかもしれません。
> long double convert_2(char* str)
> {
> long double ret;
> double a;
> sscanf(str, "%lf", &a);
> ret = a;
> return ret;
> }
> a-kuma さんに作っていただいたこのプログラムでも、ret の値はreturn したときに後ろの数桁が消滅すると思われます。
こっちの関数は、*わざと* 精度を落としています。文字列→実数の展開を
double で(つまり、%lf を使って)いるので、ret に代入している時点で
long double の精度がありません。
ありがとうございました。
関数の宣言から__fastcallを外して、TGraphFormのメソッドではない独立の関数にしたところ、うまく行きました。
いろいろお手数かけてすみませんでした。。
No.2
- 回答日時:
C++Builder を持っていないので、他のコンパイラで試してみました。
試してみたコンパイラでは、long double を printf(),scanf() で扱うとき
の書式指定子には %Lf を使います(C++Builder では、違うかもしれません)。
で、文字列を long double に変換する関数を二つ書いてみました。
#include <stdio.h>
/* きちんと long double で扱う */
long double convert_1(char* str)
{
long double ret;
sscanf(str, "%Lf", &ret);
return ret;
}
/* double で扱う */
long double convert_2(char* str)
{
long double ret;
double a;
sscanf(str, "%lf", &a);
ret = a;
return ret;
}
int main()
{
char* str = "1111.1111111111111111111111111111111111111";
long double a;
a = convert_1(str);
printf("%30.20Lf\n", a);
a = convert_2(str);
printf("%30.20Lf\n", a);
return 0;
}
実行結果は、以下の通りです。
% prog
1111.11111111111111111111
1111.11111111111108584737
「桁落ちする」ってのは、こういうことですか?
この回答への補足
回答ありがとうございます。
説明不足だったようなので、少し補足しておきます。
StrToValue(AnsiString str)の実装部分は次の通りです。
long double __fastcall TGraphForm::StrToValue(AnsiString str)
{
long double count,result;
int k;
bool pm;
k=str.Pos(".");
if(k!=0) //小数点がある場合
{
result=StrToFloat(str.SubString(1,k)); //resultに整数部分を代入
}
else
{ //小数点がない場合
result=StrToFloat(str.SubString);
return result;
}
if(StrToFloat(str)>=0) pm=true; //正の場合
else pm=false;
str.Delete(1,k); //先頭から小数点までを削除
count=1.00000000000000000000000000000000000;
count/=10;
while(str!="")
{
if(str.SubString(1,1)!="E")
//小数点以下の数値を1文字ずつresultに加えていく
{
if(pm)
result+=StrToFloat(str.SubString(1,1))*count;
else
result-=StrToFloat(str.SubString(1,1))*count;
}
else
{
str.Delete(1,1); //E-10など の計算
result*=pow(10,StrToInt(str));
break;
}
str.Delete(1,1); //先頭の文字を削除
count/=10;
}
return result;
}
StrToValue(AnsiString str) を実際には次のように使っています。
void __fastcall TGraphForm::Input(AnsiString line)
{
long double RS;
・・・
RS=StrToValue(str);
・・・
}
str="-1.55519334183474013"
であるときに StrToValue(str) を実行したところ、
RS=-1.5551933418347
となりました。後ろの数桁が消滅してしまっています。
そこで、デバッガを使って調べたところ、StrToValue(AnsiString str)のreturn直前では、
result=-1.55519334183474013
となっており、str を正確に数値に変換していました。
しかし、return 後RSを調べたところ、やはり
RS=-1.5551933418347
でした。
long double convert_2(char* str)
{
long double ret;
double a;
sscanf(str, "%lf", &a);
ret = a;
return ret;
}
a-kuma さんに作っていただいたこのプログラムでも、ret の値はreturn したときに後ろの数桁が消滅すると思われます。
(sscanf はこれまでに使ったことがなかったので、マニュアルで調べているところです)
なにか心当たりの原因があるでしょうか??
お手数をかけてすみません。。
No.1
- 回答日時:
実際に、文字列を実数に変換しているところは、どうなっているのでしょう?
long double StrToValue(AnsiString str)
{
long double value;
value = str.ToDouble();
return value;
}
なんて、やってる?
であれば、ToDouble() 自体が double を返すメソッドですから、精度が落ちる
のは仕方ないですよね。
また、有効桁が落ちているのはどうやって確認したのでしょう?
C++Builder の printf() や iostream は long double に対応しているので
しょうか?
# C++Builder を持ってないので、想像で書いてます
因みに、本題とは外れますが、
> long double StrToValue(AnsiString str)
は、str の内容を変える関数ではないでしょうから、プロトタイプは
long double StrToValue(const AnsiString& str)
としたほうが良いです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
プログラムでの数字につく”f”の...
-
float型とdouble型の変数の違い...
-
関数へのポインタで
-
数値解シミュレーション
-
C# 引数の型 自由
-
C言語でintをdoubleに
-
コンパイルした時に表示されません
-
正規分布の乱数生成
-
浮動小数点の誤差のあわせ方
-
float と double
-
MATLABで画像のヒストグラムを...
-
「割り算」 と 「分数の掛け算」
-
C# 割合の記述について
-
C言語初心者 構造体 課題について
-
C言語の複素数についてです。
-
C言語のマクローリン展開ローラ...
-
2÷3などの余りについて
-
信頼区間の1.96や1.65ってどこ...
-
std::set<int> で、ある値が何...
-
「Aに対するBの割合」と「Aに対...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
プログラムでの数字につく”f”の...
-
doubleの変数にintとintの割り...
-
c言語で、繰り返し文の中で、0....
-
C 開放してるのにエラー(doubl...
-
C言語を実行すると-infが出てき...
-
float型とdouble型の変数の違い...
-
至急です! マクロ定義で #defi...
-
C言語の型による処理速度の違い
-
関数におけるif文とreturn文に...
-
C言語 関数プロトタイプ宣言の...
-
浮動小数点の定数
-
int とdoubleの比較
-
doubleは常に%lfとするべきなのか
-
difftime()について
-
C言語でdouble型の小数点の引き...
-
たくさんの数の平均を求める方...
-
斜辺と角度て底辺と高さを出したい
-
C言語で台形公式を使った二重積...
-
float?数字の後にLがつくもの
-
listに構造体を格納
おすすめ情報