3

今日、参考書を読んでいると、こんな例が出てきました。

echo (int) ((0.1 + 0.7) * 10); // output 7

((0.1 + 0.7) * 10)は内部的に として評価されるため7.999999、 に変換するとint、結果は になります7

私もそれを正しく見つけました。コードパッドを参照してください。

しかし、さらにいくつかの例を試してみると、何か奇妙なことがわかりました。

echo (int) ((0.2 + 0.7) * 10); // output 9(コードパッド)

echo (int) ((0.7 + 0.7) * 10); // output 14(コードパッド)

などなど。値を変更するたびに、正しい答えが得られます。

((0.1 + 07) * 10)生成結果のみが他の結果と異なる理由を知りたいです。

それは本当に奇妙ですか、それとも何か不足していますか?

4

5 に答える 5

3

一般的な倍精度形式では、数値は符号ビット、11 ビットの指数、および仮数と呼ばれる 53 ビットの小数部で表されます。仮数は常に 2 52で除算された 53 ビットの非負整数です (これは、1 つの 2 進数、基数ポイント、およびさらに 52 の 2 進数として 2 進数で記述することもできます)。

.1 を正確に表すことはできません。これは、指数が -4 で仮数が 7205759403792794 / 2 52で表されます。つまり、double.1 に最も近いのは 7205759403792794•2 -52 •2 -4 = 0.1000000000000000055511151231257827021181583404541015625 です。

.7 に最も近いdoubleものは、仮数が 6305039478318694 / 2 52で、指数が -1 です。6305039478318694•2 -52 •2 -1 = 0.699999999999999555910790149937383830547332763671875 です。

これら 2 つの数値を加算すると、結果は 0.7999999999999999611421941381195210851728916168212890625 になります。これもdouble;で正確に表現できるわけではありません。最も近い表現可能な値に丸める必要があり、10 を掛けると、再度丸める必要があります。ただし、合計が 0.8 未満であることがわかります。最終結果は 8 未満なので、整数に変換すると 7 に切り捨てられます。

最もdouble近い .8 は 0.8000000000000000444089209850062616169452667236328125 です。これを 0.1000000000000000055511151231257827021181583404541015625 に加算すると、合計は 0.900000000000000499600361081320443190634250640869140625 になります。ご覧のとおり、それは .9 より大きいです。丸めと 10 の乗算の最終結果は 9 以上になるため、整数に変換すると 9 になります。

あなたが試した他のいくつかの値が切り捨てられなかったという事実は、単なる偶然です。正確に表現できないすべての値は、2 つの表現可能な値 (一方が高く、もう一方が低い) の間のどこかに収まります。より高い値に近いものもあれば、より低い値に近いものもあります。たまたま、より高い表現可能な値に近く、切り上げられた値を選択しただけです。

于 2013-04-24T14:11:07.917 に答える