JavaScript | Numberオブジェクト

javascrpit JavaScript
スポンサーリンク

0.1 + 0.2 の内部で何が起きるか詳しく教えて

この「0.1 + 0.2 がなぜ 0.3 にならないのか」は、JavaScript の数値の正体(IEEE 754) を理解するうえで、非常に大事なテーマです。
では、初心者にもわかるように コンピュータの中で何が起きているか をステップごとに見ていきましょう。

1. JavaScript の数値は全部「倍精度浮動小数点数(IEEE 754形式)」

JavaScript では 整数も小数も区別せずに「number型」 として扱います。
内部的には、すべてが IEEE 754 Double Precision(64ビット浮動小数点数) という形式で保存されています。

64ビットの内訳

区間意味ビット数
符号部正か負か1
指数部桁(2の何乗か)11
仮数部(小数部)実際の値の細かい部分52

この「仮数部」の52ビットが、0と1でしか表せないために誤差が発生します。

2. 0.1 は2進数では「割り切れない」

10進数の 0.1 を 2進数にすると、こうなります。

0.1(10) = 0.0001100110011001100110011001100...(2)
JavaScript

そう、永遠に続く循環小数なんです。

でも、コンピュータは有限のビット数しか扱えないので、
途中で 切り捨て てしまいます(52ビット分しか保存できない)。

3. 実際に保存される「0.1」の近似値

保存されている実際の値(近似)は:

0.1000000000000000055511151231257827021181583404541015625
JavaScript

つまり、ほんの少し大きいんです。

4. 同じく「0.2」も完全には表せない

0.2(10) = 0.0011001100110011...(2)
JavaScript

こちらも無限に続くので切り捨て。
保存される近似値は:

0.200000000000000011102230246251565404236316680908203125
JavaScript

つまり、これも少し大きい。

5. 足し算すると…

ではこの2つを足してみましょう。

(0.10000000000000000555…) +
(0.20000000000000001110…) =
0.30000000000000001665
JavaScript

これを64ビットの範囲に丸めて保存すると:

0.30000000000000004
JavaScript

となります。

6. 「0.3」は別の近似値

ちなみに「0.3」そのものも、内部では次のような近似値になります:

0.299999999999999988897769753748434595763683319091796875
JavaScript

つまり、「0.1 + 0.2」と「0.3」は厳密に異なるビット列を持っているのです。

7. 実際に確認してみよう

console.log(0.1 + 0.2 === 0.3);  // false
console.log(0.1 + 0.2);           // 0.30000000000000004
JavaScript
  • 0.1 + 0.2 の結果は「0.30000000000000004」
  • 0.3 の内部表現は「0.2999999999999999889…」

だから、ほんのわずかに違うので false になるわけです。

8. この誤差にどう対処するか?

実務では、こういった誤差を防ぐために次のような方法がよく使われます。

✅ 方法1:toFixed() や Math.round() で丸める

let result = 0.1 + 0.2;
result = Math.round(result * 100) / 100;
console.log(result); // 0.3
JavaScript

→ 小数第2位で丸めることで、見た目・計算上も「0.3」として扱える。

✅ 方法2:整数として計算する(通貨計算の定番)

let result = (10 + 20) / 100; // 10円 + 20円 のように「整数」で扱う
console.log(result); // 0.3
JavaScript

→ 金額計算では、円やセントなど最小単位(整数)で処理し、最後に小数点を付けるのが安全。

✅ 方法3:専用の精密計算ライブラリを使う

たとえば:

これらは 誤差なしで小数計算を行う ライブラリです。

まとめ

現象原因対処法
0.1 + 0.2 ≠ 0.32進数で0.1, 0.2を正確に表せない丸め処理 or 整数計算
浮動小数点誤差IEEE754の仕様(52bit制限)BigInt / decimal.js
==ではOKでも===でNG型や誤差が違う数値誤差を丸めて比較
タイトルとURLをコピーしました