2016-07-11 4 views
1

浮動小数点値だけを含むchar *を浮動小数点型に変換しようとしていますが、sscanf_sとatofの両方が同じ無効な結果を生成します。sscanf_sまたはatofを使用してchar *をfloatに変換すると、精度が低下するのはなぜですか?

char t[] = "2.10"; 
float aFloat(0.0f), bFloat(0.0f); 

sscanf_s(t, "%f", &aFloat); 
bFloat = atof(t); 

出力:私は無駄にその解決策を試みた答えを把握しようとする試みで同様の質問を見て

aFloat: 2.09999990 
bFloat: 2.09999990 

Converting char* to float or double

ここで与えられた解決策は、「stdlib.h」をインクルードすることで、そうした後、私は明示的に呼び出し「のstd :: atof」、まだ運にatofの呼び出しを変更しました。

+6

すべての値が正確に表現できるわけではありません。また参照してください:http://stackoverflow.com/questions/588004/is-floating-point-math-broken – NathanOliver

+0

浮動小数点!=実数。バイナリへようこそ。 @ NathanOliverのリンクを参照してください。 – davidbak

+1

あなたの質問に対するちょっとした修正。あなたの結果は完全に正当で正しい。あなたの前提と期待は無効です。 – Ped7g

答えて

3

残念ながら、浮動小数点値のすべてを明示的にバイナリ形式で表現することはできません。あなたは

float myValue = 2.10; 
+1

ありがとうございます。これは金融アプリケーションに大きな影響を与えませんか? – MikeO

+1

@MikeOセントの値を常に整数値として保存し、それを表示/非表示のために100で除算/モディファイすることによって、通貨とセントの一部に分割することはできません。 –

+1

@MikeO不正確さに対処する準備ができていない場合、金融アプリケーションに大きな影響を与えます。小数点以下のペニーをダブルカウントしたり、切り捨てることを避けるためには、一貫した丸め戦略が必要です。これらの計算には、固定小数点数値型を使用することを強くお勧めします。 – tadman

3

を言うならば、私はコメントで優れた答えを参照してください同じ結果が得られます不足している(または私は簡単にそこにそれを見つけることができませんでした)どのようにそれに対処するための一つの他のオプションを選択します。

浮動小数点数が必要な理由は、書いたはずです。あなたが偶然、金額で動作する場合(巨大なものではない)、入力値のカスタムパーサと値出力のカスタムフォーマッタを作成し、それを64b整数(* 100)として読み取り、全体で作業することができます100 *値のアプリケーション。あなたが本当に巨額で作業しているなら、大きな数字のためにいくつかの図書館を使うか、あるいはあなた自身が作成してchar *番号を使って作業するかもしれません。

Fixed-point arithmeticの特殊ケースです。

コーディングせずに大量のライブラリを利用することに興味があれば、* 100の固定小数点の変形もバグを書くのは簡単です。初めての場合それを正しく行うための十分なリソースがありません(TDDアドバイス)。

しかし、数値がコンピュータにどのように格納されているか、浮動小数点/倍精度がすべての数値を表すことができない理由を明確に学びます。浮動小数点数2.1(コンピュータ内部で使用される2)は、人間の1/3と似ています。これは、基数10で無限の小数点以下桁数で表すことはできません(1.0 == 0.99999...、基数10)。 (tobi303 @感謝)


があれば、あなたの新しいコメントを読んだ後、「これは金融アプリケーションに大きな影響を持っていませんか?」

回答:いいえ、影響はありません。正気(およびプロフェッショナル)は、浮動小数点または倍精度の金融アプリケーションを作成しません。

+1

"これと同様の状況で、人間の基本10形式は無限の小数点以下の無理な数字を表すことができない私は反対する必要があります。これは非合理化とはほとんど関係がありません。ベース10の1/3を取ると、ベース2の有限の桁数を持たない2.1(基数10)のはるかに良い等価になります – user463035818

関連する問題