操作して学ぶ
IEEE 754 可視化
0.1 + 0.2 が 0.3 にならないのは、コンピュータが数を2進の浮動小数点で持つから。 数を入力すると、符号・指数・仮数のビット分解と、そのビットが実際に表す正確な10進数(丸めなし・BigIntで厳密計算)を表示します。
1 + 11 + 52 = 64 bit / bias 1023
0
符号 (1)
01111111011
指数 (11)
1001100110011001100110011001100110011001100110011010
仮数 (52)
符号 sign
0 → 正
指数 exponent
1019 − 1023 = -4
仮数 mantissa
1.(暗黙の1)+ 小数部
入力した10進数0.1
この float64 が実際に表す正確な値0.1000000000000000055511151231257827021181583404541015625
分類正規化数
有効桁数(正確な値)55 桁
なぜ 0.1 + 0.2 ≠ 0.3 なのか
0.1 も 0.2 も、2進では割り切れない循環小数。float64 に収めた時点でわずかにズレ、 足した結果は 0.3 を float64 で表した値とも一致しません。上の入力に 0.1 + 0.2 と 0.3 を入れて、 「実際に表す正確な値」を見比べてください。
0.1 + 0.2 → 0.30000000000000004
0.3 → 0.3
値 = (−1)符号 × 1.仮数 × 2指数−bias。仮数の「暗黙の1」で1ビット得しています。 「正確な値」は、ビット列が表す有理数を BigInt で 5n 倍して10進に展開したもの(丸めなし)。 金額計算に浮動小数点を使ってはいけない理由がここにあります(整数の最小単位か固定小数点を使う)。
ここが要点
- 多くの10進小数は2進で割り切れない。0.1 は 1/10 で、分母に5を含むため2進では循環し、有限ビットに収める時点で丸められる。
- 格納された時点で誤差が乗る。0.1 も 0.2 もわずかに大きい値で保持され、足すと 0.3 の格納値とも一致しない。
- float32 は約7桁、float64 は約15〜16桁の10進有効数字。仮数のビット幅が精度を決める。
- 金額に浮動小数点は使わない。整数の最小単位(円・セント)か固定小数点・十進型を使う。