質問
重複の可能性:
C# の浮動小数点演算が不正確なのはなぜですか?
私はいくつかの数値と C# を扱ってきましたが、次のコード行の結果は予想とは異なる数値になります。
double num = (3600.2 - 3600.0);
num は 0.2 であると予想していましたが、実際には 0.1999999999998181 でした。近いのに異なる小数を生成する理由はありますか?
解決
それの訳は double
は浮動小数点データ型です。
より高い精度が必要な場合は、次の使用に切り替えることができます。 decimal
その代わり。
リテラルの接尾辞 decimal
は m なので、使用します decimal
算術 (そして、 decimal
結果)コードを次のように書くことができます
var num = (3600.2m - 3600.0m);
を使用するとデメリットがあることに注意してください。 decimal
. 。これは、データ型のサイズである 64 ビットとは対照的に、128 ビットのデータ型です。 double
. 。これにより、メモリと処理の両方のコストが高くなります。範囲も以前よりもはるかに狭いです double
.
他のヒント
理由はあります。
その理由は、double データ型の場合、数値がメモリに格納される方法では、数値 3600.2 を正確に表現できないためです。また、数値 0.2 を正確に表現することもできません。
0.2 はバイナリで無限表現を持ちます。計算を実行するためにメモリまたはプロセッサ レジスタに保存したい場合は、代わりに有限表現の 0.2 に近い数値が保存されます。このようなコードを実行しても明らかではないかもしれません。
double num = (0.2 - 0.0);
これは、この場合、double データ型で数値を表すために使用できるすべての 2 進数が数値の小数部分を表すために使用され (小数部分のみが存在します)、精度が高くなるためです。数値 3600.2 を double 型のオブジェクトに格納すると、整数部分 3600 を表すためにいくつかの桁が使用され、小数部分を表す桁数は少なくなります。精度は低く、実際にメモリに格納される小数部分は 0.2 とは十分に異なるため、double から string への変換後に明らかになります。
見る ウィキペディア
もっとうまく説明することはできません。読書を勧めることもできます すべてのコンピュータ科学者が浮動小数点演算について知っておくべきこと. 。または、関連する質問を参照してください スタックオーバーフロー.