10進数では有限なのに、2進数では無限になる理由
基本情報技術者試験やプログラミングを学び始めると、
なぜ 0.1 や 0.2 はコンピュータで誤差が出るの?
という疑問を持つ人が多くいます。
その理由は、「2進数では有限で表せない数があるから」です。
今回は、その仕組みを分かりやすく見ていきましょう。

小数を2進数へ変換する方法
2進数の小数は、
2倍して、整数部分を取り出す
という操作を繰り返して求めます。
例えば 1/3 を変換すると、
1/3 × 2 = 2/3 → 0
2/3 × 2 = 4/3 → 1(残り1/3)
残りがまた 1/3 に戻りました。
つまり、この先も同じことの繰り返しになります。
1/3 = 0.010101010101...₂
1/5 を変換すると?
同じように計算します。
1/5 × 2 = 2/5 → 0
2/5 × 2 = 4/5 → 0
4/5 × 2 = 8/5 → 1(残り3/5)
3/5 × 2 = 6/5 → 1(残り1/5)
ここで最初の 1/5 に戻ります。
つまり、
1/5 = 0.001100110011...₂
となります。
2/5 や 3/5 は?
同じように循環します。
1/5 = 0.001100110011...₂
2/5 = 0.011001100110...₂
3/5 = 0.100110011001...₂
4/5 = 0.110011001100...₂
どれも有限にはなりません。
有限になるかどうかの判断方法
実は簡単なルールがあります。
まず分数を約分します。
そして、
約分後の分母が 2 のべき乗(2、4、8、16…)だけなら、2進数では有限になります。
例えば、
| 分数 | 分母 | 2進数 |
|---|---|---|
| 1/2 | 2 | 有限 |
| 1/4 | 4 | 有限 |
| 1/8 | 8 | 有限 |
| 1/16 | 16 | 有限 |
一方、
| 分数 | 分母 | 2進数 |
| 1/3 | 3 | 無限 |
| 1/5 | 5 | 無限 |
| 1/6 | 6 | 無限 |
| 3/10 | 10 = 2×5 | 無限 |
となります。
ポイントは、
分母に「2以外の素因数」が残ると、2進数では循環小数になる
ということです。
10進数では有限なのに、2進数では無限になることがある
例えば、
1/10 = 0.1
これは10進数では有限です。
しかし2進数では、
0.00011001100110011...₂
となり、無限に続きます。
逆に、
1/2
1/4
1/8
などは10進数でも2進数でも有限になります。
10進数で無限なら、2進数でも無限?
答えは はい です。
例えば、
1/3
は、
0.333333...₁₀
ですが、
0.01010101...₂
となり、2進数でも循環します。
理由は、10進数で有限になるためには、
分母が
2 と 5
だけで構成されている必要があります。
10進数で無限ということは、
3
7
11
などの素因数が残っています。
2進数では「2」しか使えないため、それらを表すことはできません。
その結果、2進数でも必ず循環小数になります。
これが double の誤差につながる
C# の double は、
値を 2進数 で保存しています。
例えば、
double x = 0.1;
と書いても、
実際には
0.000110011001100110011...
という無限に続く2進数になります。
しかし、コンピュータは有限のビット数しか保存できません。
そのため途中で丸められ、
0.10000000000000001...
のような誤差が発生します。
これが、
0.1 + 0.2 != 0.3
になる理由です。
まとめ
- 小数を2進数へ変換するときは、「2倍して整数部分を取り出す」を繰り返す。
- 約分後の分母が 2のべき乗 なら、2進数で有限になる。
- 分母に 2以外の素因数 が残ると、2進数では循環小数になる。
1/5、2/5、3/5、4/5はすべて2進数では無限に続く。- 10進数で有限でも、2進数では無限になることがある(例:0.1、0.2)。
doubleは2進数で値を保存するため、丸め誤差が発生することがある。
この仕組みを理解すると、「なぜコンピュータでは小数の誤差が起きるのか」が納得できるようになります。








ディスカッション
コメント一覧
まだ、コメントがありません