0
0

【丸め誤差】なぜ0.1 + 0.2 ≠ 0.3となるのか?を解説する

Last updated at Posted at 2024-08-15

はじめに

前々から「0.1+0.2=0.3000.....0004と0.3にならないのは何でだろう??」といった疑問を持っていましたものの、当時は深掘りをしていませんでした。下記が問題のソースコードです。

console.log(0.1+0.2); // 0.30000000000000004

最近、Javascriptで勉強を始める中で、その理由について解説しており腑に落ちたので、本記事にて共有します。

0.1 + 0.2 ≠ 0.3となる理由

実は0.1や0.2は...

実は0.1や0.2もコンピュータの世界では、「0.1」や「0.2」と表現されないのです
その理由として、コンピュータ上では2進数で表記されることより、0.1や0.2を正確に表すことができなくなっています。実際に計算される2進数表記(toString(進数))、正確な数値(toFixed(桁数))をそれぞれ表現をすると、下記のようになります。

/* 0.1 */
// 2進数表記:0.0001100110011001100110011001100110011001100110011001101
console.log((0.1).toString(2));
// 正確な数値:0.1000000000000000055511151231257827021181583404541015625
console.log((0.1).toFixed(100));

/* 0.2 */
// 2進数表記:0.001100110011001100110011001100110011001100110011001101
console.log((0.2).toString(2));
// 正確な数値:0.200000000000000011102230246251565404236316680908203125
console.log((0.2).toFixed(100));

注) 上記の記述の場合、正確な数値にて本来は100桁分表示するので0が続くのですが、今回は説明の都合上割愛しています。

ソースコードより、2進数表記はいずれも00110011...と循環しており、最後の桁で...1101と切り上げていることが確認できます。この切り上げの影響により、0.1や0.2を正確に割り出すと微小な丸め誤差が発生するのです。

0.1 + 0.2 ≠ 0.3となる正体は何なのか?

こちらについても、上記で説明したような 「切り上げ」 の影響を受けた結果として、0.1 + 0.2 ≠ 0.3となります。実際に、0.1+0.20.3について2進数表記で比較すると下記のようになります(分かりやすいように、出力結果の項目で比較します)。

// 入力
console.log((0.1+0.2).toString(2));
console.log((0.3).toString(2));

// 出力結果
// 0.010011001100110011001100110011001100110011001100110100 (0.1+0.2)
// 0.010011001100110011001100110011001100110011001100110011 (0.3)

上記のように、2進数で比較した場合に誤差が発生することについて確認できます。
この切り上げられた数値同士が加算されることによって、最初に掲げた問題となる下記のような出力結果が生まれます。

console.log(0.1+0.2); // 0.30000000000000004

最後に

0.1 + 0.2 ≠ 0.3になる理由として、

  • 2進数表記で表すと切り上げが発生すること
  • 切り上げた数値同士を加算することで、目に見える誤差が発生すること

がありました。

皆さんのお役に立てれば幸いです!

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0