FE EXAM

小数の2進数変換

10進小数を2進数に変換する方法。0.1のような単純な小数が2進数では無限小数になる仕組みを学びます。

INTERACTIVE CONVERTER
ビット1
ビット0
入力値
0.625
2進数
0.101
検算(10進に戻す)
0.62500000
割り切れた
誤差なし
ビット精度8ビット
132
プリセット
10進小数を入力
掛け算法のやり方
小数部分を2倍して、結果が1以上ならビット「1」1未満ならビット「0」を取り出します。 残った小数部分を次のステップに渡して、同じ操作を繰り返します。
解説

📌
小数の2進数変換とは

0.62510進小数掛け算法(×2を繰り返す)0.1012進小数

整数の2進数変換は「2で割る」方法でしたが、小数部分は逆に「2を掛ける」方法(掛け算法)で変換します。 たとえば10進数の0.625は、2進数では0.101になります。

上のツールに小数を入力すると、この変換過程が1ステップずつ表示されます。 まずは「0.625」や「0.5」のように割り切れる値で試して、次に「0.1」のように割り切れない値を入力してみてください。

📌
掛け算法のやり方(具体例:0.625)

Step 1:0.625 × 2 = 1.25→ 1以上なので1Step 2:0.25 × 2 = 0.50→ 1未満なので0Step 3:0.50 × 2 = 1.00→ 1以上なので1結果: 0.625 → 0.101残り0 → 割り切れた!

掛け算法のルールは3つだけです。
小数部分に2を掛ける
・結果が1以上なら、ビット「1」を記録して、整数部分の1を取り除く(1.25 → 0.25)
・結果が1未満なら、ビット「0」を記録して、そのまま次へ進む
これを小数部分が0になるまで(または必要なビット数に達するまで)繰り返します

0.625で実際にやってみましょう。
・Step 1: 0.625 × 2 = 1.25 → 1以上なのでビット「1」。整数の1を取り除いて残り 0.25
・Step 2: 0.25 × 2 = 0.50 → 1未満なのでビット「0」。残り 0.50
・Step 3: 0.50 × 2 = 1.00 → 1以上なのでビット「1」。残り 0.00 → 終了!
記録したビットを上から順に並べると → 0.101

なぜこれで正しいのか? 2進小数の各桁は左から順に 0.5、0.25、0.125... を表します。0.101 = 1×0.5 + 0×0.25 + 1×0.125 = 0.5 + 0.125 = 0.625 ✓。掛け算法は「この値は0.5を含むか?残りは0.25を含むか?...」と順番に確認しているのです。

0.625は3ステップで小数部分がちょうど0になったので、きれいに割り切れました。小数部分が0にならない場合(例: 0.1)は、永遠に繰り返しが続く循環小数になります。次のカードで詳しく見ていきます。

📌
2進数では表せない数字がある

0.1 → 0.0001100110011...0011が無限ループ10進では有限 → 2進では無限に続く→ コンピュータは途中で打ち切る → 誤差が生じる

0.625はきれいに変換できましたが、0.1は2進数で割り切れません。掛け算法を実際にやってみると理由がわかります。


・0.1 × 2 = 0.2 → 整数部 0
・0.2 × 2 = 0.4 → 整数部 0
・0.4 × 2 = 0.8 → 整数部 0
・0.8 × 2 = 1.6 → 整数部 1
・0.6 × 2 = 1.2 → 整数部 1
・0.2 × 2 = 0.4 → ここで2行目に戻る!
0.2 → 0.4 → 0.8 → 0.6 → 0.2 → ...のサイクルが永遠に繰り返されるため、結果は 0.0001100110011... と「0011」が無限に続く循環小数になります。小数部分が途中で0.0にならない限り、この掛け算は永遠に終わりません。

10進数で 1/3 = 0.333... が割り切れないのと同じ現象です。10進法は分母が2と5の素因数だけの分数しか割り切れず、2進法は分母が2のべき乗(2, 4, 8, 16...)の分数しか割り切れません。0.1 = 1/10 の分母10には素因数5が含まれるため、2進数では永遠に割り切れないのです。

コンピュータのメモリは有限なので、この無限小数をどこかで打ち切らざるを得ません。この打ち切りによって生じるズレが丸め誤差です。プログラミングで 0.1 + 0.2 = 0.30000000000000004 になるのは、0.1も0.2もそれぞれ微小な誤差を持った近似値であり、足し算で誤差が合算されるためです。

上のツールで「0.1」を選び、ビット精度を4→8→16→32と変えてみてください。ビットを増やしても誤差は0にならないことが確認できます。

📌
意外に多い「2進数で割り切れない小数」

0.1〜0.9の小数を2進数に変換してみると、割り切れるのはたった3つだけです。残り6つはすべて循環小数になります。

10進2進結果分数で見ると
0.10.00011...循環小数1/10(分母に5が含まれる)
0.20.0011...循環小数1/5(分母に5が含まれる)
0.250.01割り切れる1/4 = 1/2²
0.30.01001...循環小数3/10(分母に5が含まれる)
0.40.0110...循環小数2/5(分母に5が含まれる)
0.50.1割り切れる1/2 = 1/2¹
0.60.1001...循環小数3/5(分母に5が含まれる)
0.70.1011...循環小数7/10(分母に5が含まれる)
0.750.11割り切れる3/4 = 3/2²
0.80.1100...循環小数4/5(分母に5が含まれる)
0.90.1110...循環小数9/10(分母に5が含まれる)

パターンは明確です。分母が2のべき乗(2, 4, 8, 16...)だけで構成される分数のみが割り切れます。0.5 = 1/2、0.25 = 1/4、0.75 = 3/4 はすべて分母が2のべき乗です。

一方、0.1 = 1/10 の分母10は 2×5 なので、素因数に5が混ざっています。2進法は「2で割る」操作の繰り返しなので、5の因数を消しきれずに永遠にループしてしまうのです。これは10進法で 1/3 = 0.333... が割り切れないのと全く同じ理由です(10の素因数は2と5なので、3を消せない)。

つまり、私たちが日常で使う10進小数の大半は、コンピュータ内部では「近似値」として扱われています。0.1円、0.3kg、0.7秒...こうした身近な値がすべて2進数では割り切れないことは、プログラミングで浮動小数点を扱う際に必ず意識すべきポイントです。

📌
割り切れない小数をコンピュータはどう扱うか

0.1= 0.0001100110011001100110011...32bit:0.00011001100110011001101ここで打切り復元:0.100000001490116...= 0.1 ではない!誤差: 0.000000001490116...(約1億分の1)

前のカードで見たように、0.1は2進数では無限に続く循環小数です。しかしコンピュータのメモリは有限なので、どこかで打ち切って近似値として保存するしかありません。この「打ち切り」の仕方には主に2つの方法があります。


切り捨て(truncation):指定ビット数で単純に切る。0.0001100110011... を8ビットなら 0.00011001 で終了。実装が簡単だが、常に本来の値より小さくなる
最近接丸め(round to nearest):切り捨てと切り上げのうち、より近い方を選ぶ。IEEE 754(浮動小数点の国際規格)ではこの方式が標準。誤差が偏りにくい

どちらの方式でも、打ち切った瞬間に元の値とはわずかにずれた「別の数」になります。このずれが「丸め誤差」です。たとえば32ビットの単精度浮動小数点で0.1を保存すると、実際に保存されるのは 0.100000001490116... という微妙に違う値です。

1回の丸め誤差はごくわずかですが、計算を何万回も繰り返すと誤差が蓄積して無視できなくなります。金融システムで「1円ずれる」、科学計算で「結果が不安定になる」といった問題はすべてここに起因します。対策として、金額計算では整数に変換して扱う(100円→10000)、科学計算ではDecimal型や多倍長演算を使うなどの方法が取られます。

📌
ビット精度とは

0.1 の近似精度4bit37.5%8bit2.3%16bit0.02%32bit極小64bit超極小← 粗い精密 →

ビット精度とは、小数部分を何ビットで表現するかという設定です。日常に例えると「小数第何位まで書くか」と同じです。小数第1位(3.1)より小数第4位(3.1416)の方が円周率に近いように、ビット数が多いほど元の値に近づきます。

0.1を例に、ビット数を増やしていくと誤差がどう変わるか見てみましょう。
4ビット:0.0001 = 0.0625(誤差 37.5%、全然違う値になる)
8ビット:0.00011001 = 0.09765625(誤差 2.3%、だいぶ近づく)
16ビット:誤差 約0.002%(小数第5位まで正確)
32ビット(単精度):誤差 約0.000000006(小数第8位まで正確)
64ビット(倍精度):誤差 約10の-17乗(小数第16位まで正確、でもまだ0ではない)
ビットを2倍にすると誤差はおおよそ半分以下になりますが、循環小数の場合は永遠に0にはなりません。一方、0.5や0.625のような割り切れる小数は、少ないビット数でも誤差が完全に0になります。

コンピュータでよく使われるビット精度は以下の通りです。
32ビット(単精度 / float):小数部分に23ビット使用。有効桁数は約7桁。ゲームや画像処理など速度優先の用途に
64ビット(倍精度 / double):小数部分に52ビット使用。有効桁数は約15桁。ほとんどのプログラミング言語のデフォルト
128ビット(四倍精度):小数部分に112ビット使用。有効桁数は約34桁。天文学や暗号計算など極めて高い精度が必要な場合

ビット数を増やせば精度は上がりますが、メモリ使用量も増え、計算速度は遅くなります。実務では金額計算に浮動小数点を使わず整数で扱う(100円→10000に変換)、あるいはDecimal型(10進浮動小数点)を使うといった対策も取られます。上のツールのビット精度スライダーを動かして、誤差の変化を確認してみてください。

📌
整数と小数が含まれる数字の場合

5.75整数部 5→ 割り算法 →101小数部 0.75→ 掛け算法 →.11101.11

5.75のように整数部分と小数部分の両方がある場合、一度に変換するのではなく、整数と小数を分けてそれぞれ別の方法で変換し、最後に小数点でくっつけます。これは整数と小数で変換アルゴリズムが異なるためです。

ステップ1: 整数部分(5)を割り算法で変換
・5 ÷ 2 = 2 あまり 1
・2 ÷ 2 = 1 あまり 0
・1 ÷ 2 = 0 あまり 1
→ あまりを下から読んで 101

ステップ2: 小数部分(0.75)を掛け算法で変換
・0.75 × 2 = 1.5 → 整数部 1
・0.5 × 2 = 1.0 → 整数部 1(小数部が0になったので終了)
→ 整数部を上から読んで .11

ステップ3: 小数点でつなげる
整数部 101 + 小数部 .11 = 101.11
検算: 1×4 + 0×2 + 1×1 + 1×0.5 + 1×0.25 = 4 + 1 + 0.5 + 0.25 = 5.75 ✓

ポイントは整数部は「あまりを下から読む」、小数部は「整数部を上から読む」と読む方向が逆であることです。この2つは混同しやすいので注意してください。上のツールで「5.75」を入力すると、この手順をアニメーションで確認できます。

練習問題

🎯
基本情報技術者 練習問題

Q1.10進数の 0.375 を2進数に変換したものはどれか。
A.0.010
B.0.011
C.0.101
D.0.110
Q2.10進数の 0.1 を2進数に変換すると、どのような特徴があるか。
A.ちょうど割り切れる
B.循環小数になり、正確に表現できない
C.変換できない
D.整数になる

関連コンテンツ

小数の2進数変換 | Vizigo