7

これは、その場でしか失敗しない種類のコードのように感じますが、私はそれを私が見ているものを表すコードスニペットに適合させようとします。

float f = myFloat * myConstInt; /* Where myFloat==13.45, and myConstInt==20 */
int i = (int)f;
int i2 = (int)(myFloat * myConstInt);

コードをステップスルーした後、i == 269、およびi2==268。違いを説明するためにここで何が起こっているのですか?

4

5 に答える 5

15

浮動小数点演算は、宣伝されているよりも高い精度で実行できます。しかし、float f に格納するとすぐに、余分な精度が失われます。もちろん、結果を int にキャストするまでは、2 番目のメソッドでその精度が失われることはありません。

編集:この質問を参照してください おそらく私が提供したよりも良い説明のために。

于 2010-03-24T16:45:49.173 に答える
4

浮動小数点変数は無限に正確ではないためです。そのような精度が必要な場合は、小数を使用してください。

さまざまな丸めモードもこの問題に影響を与える可能性がありますが、精度の問題は、ここで発生している問題、AFAIKです。

于 2010-03-24T16:45:24.470 に答える
2

浮動小数点の精度は限られており、10 進数ではなく 2 進数に基づいています。10 進数の 13.45 は、2 進浮動小数点では正確に表現できないため、切り捨てられます。20 を掛けると、精度の低下がさらに誇張されます。この時点で、268.999... - 269 ではありません - したがって、整数への変換は 268 に切り捨てられます。

最も近い整数に丸めるには、整数に戻す前に 0.5 を追加してみてください。

「完全な」算術演算を行うには、Decimal または Rational の数値型を使用してみてください。C# には両方のライブラリがあると思いますが、確実ではありません。ただし、これらは遅くなります。

編集-これまでのところ「10進数」タイプを見つけましたが、有理数ではありません-それが利用可能であることについて間違っているかもしれません。10 進浮動小数点は 2 進と同様に不正確ですが、これは私たちが慣れ親しんだ種類の不正確さであるため、それほど驚くべき結果は得られません。

于 2010-03-24T16:53:02.403 に答える
1

と置換する

double f = myFloat * myConstInt;

同じ答えが得られるかどうかを確認します。

于 2010-03-24T16:48:50.193 に答える
1

別の説明をしたいと思います。

これが私が注釈を付けたコードです(フロートを分析するためにメモリを調べました):

float myFloat = 13.45; //バイナリでは 1101.01110011001100110011
 int myConstInt = 20;
 float f = myFloat * myConstInt; //バイナリでは正確に 100001101 (10 進数で 269)
 int i = (int)f; // float 269 を int 269 に変換します -- 驚くことではありません
 int i2 = (int)(myFloat * myConstInt);//「余分な精度」により 268 に丸められます

計算を詳しく見てみましょう。

  • f = 1101.01110011001100110011 * 10100 = 100001100.111111111111111 111

    スペースの後の部分はビット 25 ~ 27 であり、ビット 24 が切り上げられるため、値全体が 269 に切り上げられます。

  • int i2 = (int)(myFloat * myConstInt)

    myfloat は計算のために倍精度に拡張されます (0 が追加されます): 1101.01110011001100110011000000000000000000000000000

    マイフロート * 20 = 100001100.1111111111111111110000000000000000000000000

    ビット 54 以降は 0 であるため、丸めは行われず、キャストの結果は整数 268 になります。

    (拡張精度が使用されている場合、同様の説明が機能します。)

更新:私は自分の答えを改良し、 「フロートがフロートのように動作しない場合」という本格的な記事を書きました

于 2010-03-25T19:33:45.400 に答える