float a = 0;
while (true)
{
a++;
if (a > 16777216)
break; // Will never break... a stops at 16777216
}
このコードで float 値が 16777216 で増加しなくなる理由を誰かに説明してもらえますか?
編集:
またはさらに単純です:
float a = 16777217; // a becomes 16777216
float a = 0;
while (true)
{
a++;
if (a > 16777216)
break; // Will never break... a stops at 16777216
}
このコードで float 値が 16777216 で増加しなくなる理由を誰かに説明してもらえますか?
編集:
またはさらに単純です:
float a = 16777217; // a becomes 16777216
頭のてっぺんからのIEEE-754浮動小数点数(32ビット)の短いまとめ:
(sign ? -1 : +1) * 2^exponent * (1.0 + mantissa)
1001 0000 0000 0000 0000 000 = 2^-1 + 2^-4 = .5 + .0625 = .5625
1.5625
今あなたの例に:
16777216 は正確に 2 24であり、次のように 32 ビット浮動小数点として表されます。
10010111
)0 10010111 00000000000000000000000
(+1) * 2^24 * (1.0 + .0) = 2^24 = 16777216
では、16777217 という数字、つまり 2 24 +1を見てみましょう。
(+1) * 2^24 * (1.0 + 2^-24) = 2^24 + 1 = 16777217
16777217 は float では正確に表すことができません。float が正確に表すことができる次に大きい数値は 16777218 です。
したがって、float 値 16777216 を 16777217 にインクリメントしようとしますが、これは float では表すことができません。
その値を 2 進表現で見ると、1 と多数のゼロ、つまり1 0000 0000 0000 0000 0000 0000
、正確に 2^24 であることがわかります。つまり、16777216 で、数字が 1 桁増えただけです。
これは浮動小数点数であるため、これは、まだ格納されている (つまり、精度の範囲内である) 末尾の最後の桁も左にシフトされることを意味します。
おそらく、あなたが見ているのは、精度の最後の桁が 1 よりも大きいものにシフトしたため、1 を追加しても、もはや何の違いも生じないということです。