情報Ⅰ 最強120講義

小数の表現と誤差(浮動小数点)|情報Ⅰ 最強120講義 第42講

数強塾グループの一流講師陣 一流のライブ授業×最高品質の映像授業×サボれないコーチング

こんにちは、数強塾代表の藤原進之介です。この記事は参考書『藤原進之介の最強120講義』の第42講「小数の表現と誤差(浮動小数点)」のWeb版です。共通テスト「情報Ⅰ」での重要度はA(頻出。得点差がつく)、情報Ⅱでの接続先は(3)情報とデータサイエンスです。

この講は、私が授業で「説明」より先に「実行」から入る数少ない単元です。画面に False と出た瞬間、生徒は自分から理由を聞きにきます。2進数と16進数の変換そのものは第40講「基数変換」、整数の有限性と負の数の表し方は第41講「負の数の表現と2の補数」で扱いました。本講は小数の側を担当します。

1. この講の問い

0.1 を10回足しても、なぜ 1 にならないのか。

2. 結論

2進数の有限小数で書ける分数は、既約分数にしたときの分母が2の累乗であるものに限られます。0.1 = 1/10 は分母に 5 を含むので該当せず、10進数で 1/3 が 0.333… と循環するのとまったく同じ理由で、2進数では無限に循環します。有限のビット数しか持たないコンピュータはそれを途中で打ち切るしかなく、格納された瞬間に 0.1 は 0.1 ではなくなっています

浮動小数点数は小数点の位置を指数で持つことで、広い範囲を少ないビットで表す方式です。その代償として有効桁数がどこでも一定になり、丸め誤差・桁落ち・情報落ちという固有の壊れ方をします。

3. なぜそうなるのか

3-1. まず現象を見る

私は授業でこの単元を、説明ではなく実行から始めます。

print(0.1 + 0.2 == 0.3)
False

初めて見ると、たいていの生徒は「Python のバグですか」と言います。バグではありません。C でも Java でも JavaScript でも表計算ソフトでも、同じことが起きます。これは言語の問題ではなく、2進数で小数を表すという方式そのものの帰結です。

もう一つ見せます。

s = 0.0
for i in range(10):
    s += 0.1
print(s, s == 1.0)
0.9999999999999999 False

0.1 を10回足したのに 1 になりません。しかも面白いことに 0.1 * 101.0 になります。足し算だけが失敗する。 ここまで見せると、生徒は自分から「なぜ」を聞きにきます。この講はそこから始めます。

3-2. なぜ 0.1 は2進数で表せないのか

10進数で 1/3 が書けないことは、誰でも知っています。

1 ÷ 3 = 0.333333… 。割り切れません。0.333 と書けばそれは 1/3 ではないし、3 を何個並べても 1/3 にはなりません。だからといって「10進数は欠陥だ」とは誰も言いません。10進数で有限小数になるのは、既約分数の分母が 2 と 5 だけでできているときだけだからです。1/2 = 0.5、1/4 = 0.25、1/5 = 0.2、1/8 = 0.125 は書けます。1/3、1/6、1/7 は書けません。

2進数でも構造はまったく同じで、基数が 10 から 2 に変わるだけです。

2進数の有限小数で書けるのは、既約分数にしたときの分母が2の累乗である分数だけ。

これが本講の全部です。この1行から、以降のすべてが説明できます。

2進小数の各桁の重みは、小数点以下1桁目から順に 1/2, 1/4, 1/8, 1/16, … です。有限桁で止めた数は、必ず「何かを 2k で割った数」になります。だから分母に 2 以外の素因数(3 でも 5 でも 7 でも)が1個でも残っていたら、有限では絶対に書けません。

0.1 = 1/10 = 1/(2×5) です。分母に 5 がいます。 だから2進数では有限になりません。0.2 = 1/5 も、0.3 = 3/10 も、0.7 = 7/10 も同じ理由でアウトです。逆に 0.5 = 1/2、0.25 = 1/4、0.75 = 3/4、0.125 = 1/8 は、分母が2の累乗なのでぴったり表せます。

ここが分かれ道

「10進数で切りのいい数」と「2進数で切りのいい数」は別物です。私たちが 0.1 を切りのいい数だと感じるのは、たまたま10本の指で数を数える種族だからにすぎません。コンピュータにとって切りのいい小数は 0.5 と 0.25 と 0.125 であって、0.1 ではありません。

3-3. だから丸めるしかない

0.1 を2進数に直すと、実際にこうなります(筆算は 4-1 で示します)。

0.1(10進) = 0.0001100110011001100110011…(2進) = 0.0 と、そのあと「0011」が無限に循環

10進数の 1/3 = 0.333… とまったく同じ構造です。コンピュータの持てるビット数は有限なので、どこかで打ち切ります。打ち切るとき、単に切り捨てるのではなく最も近い表せる数に丸めます(最近接丸め)。この操作で生じるずれが丸め誤差です。

Python に 0.1 の中身を20桁まで見せてもらうと、こうなります。

0.10000000000000000555

0.1 は 0.1 ではありません。 0.1 より 5.55×10−18 ほど大きい、別の数です。だから 0.1 + 0.2 が 0.3 にならないのは当たり前で、そもそも足す前の 0.1 も 0.2 も、答えの 0.3 も、3つとも本物ではないのです。

ここで多くの参考書は「誤差が出ます、注意しましょう」で終わります。私はそこで止めたくありません。「では、そのずれは無秩序なのか」という問いが残っているからです。答えは「無秩序ではない。完全に決まっている」です。次に見る内部構造を知れば、どの数がどれだけずれるかは計算で出せます。

3-4. なぜ「浮動」小数点なのか

先に、小数点の位置を固定してしまう方式(固定小数点)を考えてみます。たとえば8ビットのうち上位4ビットを整数部、下位4ビットを小数部と決める。すると刻みは 1/16 = 0.0625 ずつ、範囲は 0 から 15.9375 までになります。

この方式には動かしがたい欠陥が2つあります。

  • 欠陥1:大きい数を扱うと小数部の桁が足りない。 惑星の距離のような大きな数を表そうとすると、整数部にビットを回すしかなく、小数部が消えます
  • 欠陥2:小さい数を扱うと整数部が丸ごと無駄になる。 電子の質量のような小さな数では、整数部の4ビットはずっと 0 のままです。情報を1ビットも運ばないビットに、貴重な枠を使っていることになります

つまり固定小数点は、「どんな大きさの数が来るか」を設計時に決め打ちしなければならない。決め打ちを外すと破綻します。

そこで発想を変えます。小数点の位置を、数値ごとに動かす。 そして動かした量を別枠に記録しておく。

これは科学記数法とまったく同じ考え方です。人間も「光速 = 2.998 × 108 m/s」「電子の質量 = 9.109 × 10−31 kg」と書きます。有効数字(2.998 / 9.109)と桁(108 / 10−31)を分けて持つ。 桁がどれだけ違っても、有効数字の欄は4桁で足ります。

コンピュータもこれをやります。基数を 10 から 2 に変えるだけです。

値 =(符号)× 1.(仮数)× 2(指数)

小数点が数値ごとに「浮動」するので浮動小数点数といいます。この設計の見返りと代償は、はっきりしています。

  • 見返り:たった64ビットで 10−308 から 10308 までを扱えます。固定小数点では逆立ちしても届きません
  • 代償有効桁数がどこでも一定になります。 仮数の欄の幅は固定なので、1 の近くだろうと 1016 の近くだろうと、保持できる有効数字の本数は同じです

この代償が、以降のすべての誤差の原因です。「絶対的な精度」ではなく「相対的な精度」が一定だ、と言い換えてもよい。1 の近くでは刻みが 2.2×10−16 しかないのに、1016 の近くでは刻みが 2 になります。1016 のあたりでは、整数ですら1つおきにしか表せません。

表せる数の「刻み」は、値が2倍になるたびに2倍になる 0.51248 刻み 1/8刻み 1/4刻み 1/2 どの区間にも同じ本数だけ数が入る=有効桁数はどこでも一定 (実際の倍精度では1区間に 2 の52乗 個。図は本数を減らした模式図)
図1 刻みは値に比例して広がる(模式図)

3-5. 64ビットの内訳(符号・指数・仮数)

現在ほとんどの環境で使われている倍精度(IEEE 754 の binary64、Python の float)は、64ビットをこう分けます。

倍精度浮動小数点数(64ビット)の中身 仮数部 52ビット 符号部 1ビット(0=正 / 1=負) 指数部 11ビット 例:0.1 を入れたときの中身 符号 0 指数 01111111011 = 1019 1019 − 1023 = −4  これが 2 の何乗かを表す 仮数 1001100110011001100110011001100110011001100110011010 ↑ 末尾は本来 …1001。最近接丸めで1つ繰り上がっている 値 =(−1)符号 × 1.仮数 × 2(指数−1023) 0.1 の場合 = 1.6 × 2−4
図2 符号1ビット・指数11ビット・仮数52ビット
ビット数 役割
符号 1 0 なら正、1 なら負
指数 11 2の何乗か(1023 を引いた値が実際の指数)
仮数 52 1.xxxx… の小数部分
合計 64 1 + 11 + 52

指数に 1023 を足してから格納するのは、負の指数も符号なしの整数として書けるようにするためです。11ビットなら 0〜2047 が書けるので、1023 を引けば −1023〜1024 が表せます。第41講で見た2の補数を使ってもよさそうなものですが、こちらのほうが指数の大小比較がビット列の大小比較のまま使えるという利点があります。

仮数が 52 ビットなのに「1.xxx」の 1 が要らないのは、2進数だからです。0 でない数を正規化すると、先頭は必ず 1 になります(10進の科学記数法では先頭が 1〜9 のどれかですが、2進数では 1 しかありません)。分かりきっている 1 を書く必要はないので省く。書かないことで52ビットが53ビット分の精度になります。 これを「ケチ表現」と呼ぶことがあります。

53ビットの精度は10進に直すとおよそ15.95桁です。だから倍精度の float は、どんな大きさの数でも有効数字およそ15〜16桁しか持てません。

3-6. 誤差の4種類を区別する

「誤差」とひとくくりにすると、対処法が立ちません。原因が違えば直し方も違います。

種類 何が起きるか 原因
丸め誤差 表せない数を、最も近い表せる数に置き換える 2進数で書けない小数があるから。入力した瞬間に発生
桁落ち ほぼ等しい2数の引き算で有効桁が大量に消える 上位の桁が消え、下位の信用できない桁が主役に昇格するから
情報落ち 桁の違いすぎる数を足すと小さいほうが消える 大きい数の刻みが粗く、小さい数が仮数の欄に入らないから
打ち切り誤差 無限に続く手続きを有限回でやめたずれ 2進数のせいではなくアルゴリズムのせい

桁落ちについて、もう少し丁寧に説明します。1.2345678901234567 と 1.2345678901234321 を引くと、答えは 0.0000000000000246 です。元の2つは16桁の有効数字を持っていたのに、答えの有効数字は3桁しか残っていません新しい誤差が生まれるのではありません。元からあった誤差の割合が、一気に拡大するのです。

情報落ちは逆向きです。1016 のあたりでは刻みが 2 なので、1016 に 1 を足しても答えは 1016 のままです。1 には行き場がありません。これを1万回繰り返しても、1016 は1ミリも動きません。

そして重要なのは、桁落ちと情報落ちは、計算の順序や式の形を変えるだけで劇的に改善することです。小さい数から先に足す、引き算を有理化して形を変える——それだけで有効桁が戻ってきます。4-4 で実際に見せます。

3-7. 国の資料はここをどう書いているか(2026年8月時点)

私は、この単元について一次資料の全文検索をかけました。結果は予想以上にはっきりしていました。同じ語が資料ごとに何回出るかを数えると、情報Ⅰと情報Ⅱの分水嶺がそのまま数字になります。すべてPDFをテキスト化し、空白を除いて全文検索したものです(2026年8月3日、当方で実施)。

学習指導要領
解説 情報編
情報Ⅰ
教員研修用教材
情報Ⅱ
教員研修用教材
IPA 基本情報
シラバス Ver.9.2
誤差 1 27 16 7
丸め(丸め誤差) 0 0 0 1
浮動(浮動小数点) 0 1 1 2
有効桁・有効数字 0 0 0 0
桁落ち 0 0 0 1
情報落ち 0 0 0 1
打切り誤差 0 0 0 1
仮数 0 0 0 1
固定小数点 0 0 0 1
絶対誤差・相対誤差 0 0 0 各1

読み取れることが3つあります。

第一に、学習指導要領解説 情報編の全文に「誤差」は1回しかありません。 その1回が、情報Ⅰ(3)ア(ア)のこの文です。

コンピュータでは定められたビット数のデータが扱われ,表現できる値の範囲や精度が有限であることで,計算結果は原理的に誤差を含む可能性がある——文部科学省「高等学校学習指導要領(平成30年告示)解説 情報編」平成30年7月

第41講(2の補数)が根拠にしたのとまったく同じ1文です。国の設計上、整数のオーバーフローも小数の丸め誤差も、この1行から派生しています。

第二に、誤差の種類の名前は、高校の一次資料に1つも存在しません。 丸め誤差・桁落ち・情報落ち・打切り誤差・有効桁数・仮数・固定小数点——全部ゼロです。これらが名前を持って現れるのは、IPA の基本情報技術者試験シラバス Ver.9.2(掲載 2026年1月8日)だけです。しかも IPA は、誤差を2つの別々の項目に分けて置いています。

(3)算術演算と精度 加減乗除,表現可能な数値の範囲,シフト演算,演算精度(誤差とその対策)など,コンピュータにおける算術演算を理解する。
用語例 論理シフト,算術シフト,桁落ち,情報落ち,オーバーフロー(あふれ),アンダーフロー,単精度,倍精度——IPA「基本情報技術者試験(レベル2)シラバス Ver.9.2」大分類1 中分類1「離散数学」
(3)数値解析 二分法,補間法など,近似解を数値的に求める考え方や計算過程で生じる誤差を理解する。
用語例 ニュートン法,絶対誤差,相対誤差,丸め誤差,打切り誤差——同上 中分類2「応用数学」

桁落ちと情報落ちは「コンピュータの算術」の側、丸め誤差と打切り誤差は「数値解析」の側に分けられています。 これは分類として正確です。桁落ち・情報落ちは有限のビット幅から出る現象であり、打ち切り誤差はアルゴリズムから出る現象だからです。3-6 で私が打ち切り誤差だけ別扱いにしたのは、この区分と同じ理由によります。

第三に、情報Ⅰ教員研修用教材の「誤差」27回は、ほぼすべて第3章に集中しています。 そして置かれている場所が意外です。誤差の話は独立した学習項目ではなく、学習11「コンピュータの仕組み」の後半、つまり論理演算・論理回路と同じ回の中に同居しています。教材はまず箱の比喩を出します。

コンピュータで変数は指定されたビット数の箱に入っていると考える。この箱(定められたビット数)に収まるものであれば誤差は生じないが,収まらないものは誤差が生じる。例えば,15 ビットの箱を準備したとき,13 ビットの魚 A は箱に収まるが,20 ビットの魚 B は箱に入らない。このとき失われた 5 ビットが計算誤差の原因となる。——文部科学省「高等学校情報科『情報Ⅰ』教員研修用教材」第3章(令和2年7月)

そして Python で 0.28 − 0.27 を計算させ、こう書きます。

小数の 0.28 から小数 0.27 を引くと,本来であれば計算結果は 0.01 になるはずだが,プログラムを実行した結果を見ると 0.01 にはならず,コンピュータの計算誤差が発生していることが分かる。——同上

さらに演習3が良いのです。

「0.28-0.27」のような計算の誤差は一見すると微々たる誤差でしかないが,実際に惑星探査機が地球から木星まで行って帰る軌道計算に使用した場合,このような計算誤差が大きな問題になるケースがある。それはなぜか考えてみましょう。また,「0.28-0.27」の計算の誤差を起こさない方法を考えてみましょう。——同上 演習3

「誤差を起こさない方法を考えてみましょう」。 国の教材は、誤差を「注意事項」ではなく解くべき問題として置いています。そして教員向けの「指導上の留意点」に、答えの方向が書いてあります。

誤差がない計算をする方法は変数の型を変える方法や,整数にして計算し,計算した結果を小数にするなど,解決方法が複数あることを示す。——同上(学習活動と展開 展開2 指導上の留意点)

「整数にして計算し、計算した結果を小数にする」。 これは実務でそのまま使われている定石です。金額を円単位の整数で持つ、という設計そのものです。本講の 4-7 でこれを具体的にやってみせます。国の教材が指し示している方向を、最後まで歩けばよいのです。

なお、解説の情報Ⅰ(3)イ(ア)には、もう一つ見逃せない文があります。

コンピュータの能力を適切に判断する力,精度とデータ容量のトレードオフの関係などを踏まえ,コンピュータを適切に活用する力を養う。その際,計算などによって意図しない結果が生じたときに,データの扱い方や精度,計算の手順などに目を向けて改善しようとする態度を養うことが考えられる。——文部科学省「高等学校学習指導要領(平成30年告示)解説 情報編」平成30年7月

「計算の手順に目を向けて改善する」。 桁落ちと情報落ちの対策そのものが、態度目標として書かれています。名前は無くても、やるべきことは書かれているのです。

4. 手で確かめる

以下のコードと出力は、すべて手元の Python 3 で実際に実行し、出力を確認したものです(2026年8月3日)。数値はすべて独立に検算しています。

4-1. 0.1 を2進数に手で直す(筆算)

10進小数を2進小数に直す筆算は、「2倍して、1の位を書き取り、1の位を捨てる」を繰り返すだけです。

計算 結果 書き取るビット 次に使う小数部
1 0.1 × 2 0.2 0 0.2
2 0.2 × 2 0.4 0 0.4
3 0.4 × 2 0.8 0 0.8
4 0.8 × 2 1.6 1 0.6
5 0.6 × 2 1.2 1 0.2 ←2回目と同じ
6 0.2 × 2 0.4 0 0.4
7 0.4 × 2 0.8 0 0.8
8 0.8 × 2 1.6 1 0.6
9 0.6 × 2 1.2 1 0.2

5回目の終わりで 0.2 に戻りました。 2回目の入口と同じ小数部です。同じ数が出た以上、そこから先は同じ計算の繰り返しにしかなりません。だから 0.1(10進)は 2進で「0.0」のあとに「0011」が無限に循環します。プログラムでも循環の開始位置1・循環節長4・循環節「0011」を確認しました。

なぜ止まらないのかも、この表から分かります。この筆算が止まるのは、途中で小数部がちょうど 0 になったときだけです。小数部が 0 になるには、分母の 5 が「2倍の繰り返し」で消えなければなりません。2 を何回かけても 5 は消えません。 だから止まらない。1/3 を10進で割り続けても止まらないのと、まったく同じことです。

4-2. 実際の値を見る

print(0.1 + 0.2 == 0.3)
print(0.1 + 0.2)
print(format(0.1, '.20f'))
print(format(0.2, '.20f'))
print(format(0.3, '.20f'))
False
0.30000000000000004
0.10000000000000000555
0.20000000000000001110
0.29999999999999998890

0.1 は少し大きく、0.2 も少し大きく、0.3 は少し小さい。 だから 0.1 + 0.2 は 0.3 を上に追い越します。丸めの向きが上・上・下とばらついた結果です。ばらついているのは偶然ではなく、それぞれの数に最も近い表せる数がどちら側にあるかで決まっています。

厳密な値も見られます。

from decimal import Decimal
print(Decimal(0.1))
0.1000000000000000055511151231257827021181583404541015625

この55桁が、あなたのコンピュータの中にある「0.1」の正体です。 途中で切れているのではなく、これで終わりです。ぴったりこの値が入っています。

分数でも書けます。

from fractions import Fraction
print(Fraction(0.1))
print(36028797018963968 == 2**55)
3602879701896397/36028797018963968
True

分母が 255 です。3-2 で述べた「2進数で書けるのは分母が2の累乗の分数だけ」が、そのまま目の前に出ています。 コンピュータは 1/10 を格納したのではなく、1/10 に最も近い「分母が2の累乗の分数」を格納したのです。

4-3. 足し算を1回ずつ追う

s = 0.0
for i in range(10):
    s += 0.1
    print(i + 1, s)
1 0.1
2 0.2
3 0.30000000000000004
4 0.4
5 0.5
6 0.6
7 0.7
8 0.7999999999999999
9 0.8999999999999999
10 0.9999999999999999

面白いのは3回目でずれたのに、4回目でずれが消えていることです。0.4 に最も近い表せる数と、0.30000000000000004 + 0.1 の結果が一致してしまうので、表示上は元に戻ります。誤差は消えたのではなく、たまたま同じ枠に落ちただけです。そして8回目でまた顔を出し、最後まで残ります。

print(sum([0.1] * 10), sum([0.1] * 10) == 1.0)
print(0.1 * 10, 0.1 * 10 == 1.0)
0.9999999999999999 False
1.0 True

足し算は失敗し、かけ算は成功します。 10回足すと丸めが10回起きますが、10倍は丸めが1回で済むからです。丸めの回数が誤差の量を決めます。

4-4. 4種類の誤差を再現する

丸め誤差(教材の例をそのまま)

print(28 - 27)
print(0.28 - 0.27)
print(format(0.28 - 0.27, '.20f'))
1
0.010000000000000009
0.01000000000000000888

整数なら合う。小数だと合わない。教材の図表8そのものです。

桁落ち

import math
from decimal import Decimal, getcontext
getcontext().prec = 50
naive = math.sqrt(1e8 + 1) - math.sqrt(1e8)
exact = (Decimal(10)**8 + 1).sqrt() - (Decimal(10)**8).sqrt()
print(naive)
print(exact)
print(1.0 / (math.sqrt(1e8 + 1) + math.sqrt(1e8)))
5.000000055588316e-05
0.000049999999875000000624999996093750027343750
4.9999999874999996e-05

素朴に引き算した答えは、正しい値と7桁目までしか合っていません(相対誤差 1.4×10−8)。float は16桁近い精度を持っていたのに、引き算1回で半分以上を失いました

ところが、分子と分母に「2つの平方根の和」をかけて有理化した形にすると、答えは正しい値と16桁一致します(相対誤差 9.0×10−17)。同じ値を求めているのに、計算式の形を変えただけで精度が8桁戻りました。 これが解説の言う「計算の手順に目を向ける」ということです。

情報落ち

import math
print(1e16 + 1 == 1e16)
print(1e16 + 2)
print(math.ulp(1.0), math.ulp(1e16))
True
1.0000000000000002e+16
2.220446049250313e-16 2.0

1016 に 1 を足しても増えません。2 を足すとやっと動きます。math.ulp が返しているのは「その値の次に表せる数までの距離」で、1 の近くでは 2.2×10−16、1016 の近くでは 2 です。1016 のあたりでは、偶数しか表せません。

順序を変えると結果が変わることも見ておきます。

import math
small = [1e-3] * 10000
t1 = 1e16
for v in small:
    t1 += v
t2 = 0.0
for v in small:
    t2 += v
print(t1)
print(t2 + 1e16)
print(math.fsum([1e16] + small))
1e+16
1.000000000000001e+16
1.000000000000001e+16

大きい数を先に置くと、あとから足した1万個の 0.001 が1個残らず消えます。 小さい数どうしを先に合計してから大きい数に足せば、ちゃんと 10 だけ増える。誤差なしで合計する math.fsum の答えとも一致しました。足す順番を変えただけで、消えた 10 が戻ってきたのです。

打ち切り誤差

import math
for n in [10, 100, 1000, 10000, 100000]:
    s = 0.0
    for k in range(n):
        s += (-1)**k / (2*k + 1)
    print(n, 4*s, abs(4*s - math.pi))
10 3.0418396189294032 0.09975303466038987
100 3.1315929035585537 0.00999975003123943
1000 3.140592653839794 0.000999999749998981
10000 3.1414926535900345 9.99999997586265e-05
100000 3.1415826535897198 1.0000000073340232e-05

項数を10倍にすると誤差が10分の1になります。これは丸め誤差ではありません。 無限級数を有限で打ち切ったことによる誤差であり、たとえ無限精度で計算しても同じだけ残ります。原因が違うから、対策も違う(項数を増やす、収束の速い式に変える)のです。

4-5. 内部のビットを直接見る

import struct
def bits64(v):
    return format(struct.unpack('>Q', struct.pack('>d', v))[0], '064b')
for v in [1.0, 2.0, -2.0, 0.5, 3.5, 0.1]:
    b = bits64(v)
    print(v, b[0], b[1:12], int(b[1:12], 2) - 1023, b[12:])
1.0 0 01111111111 0 0000000000000000000000000000000000000000000000000000
2.0 0 10000000000 1 0000000000000000000000000000000000000000000000000000
-2.0 1 10000000000 1 0000000000000000000000000000000000000000000000000000
0.5 0 01111111110 -1 0000000000000000000000000000000000000000000000000000
3.5 0 10000000000 1 1100000000000000000000000000000000000000000000000000
0.1 0 01111111011 -4 1001100110011001100110011001100110011001100110011010

読み方を確認します。

  • 1.0 は 1.0 × 20。指数欄は 1023 + 0 = 1023 = 01111111111、仮数はすべて 0
  • 2.0 は 1.0 × 21。指数が1つ増えただけで、仮数は 1.0 と同じ
  • −2.0 は 2.0 と符号ビットだけが違う。残り63ビットは完全に同一です。第41講の2の補数とはまったく違う仕組みで、浮動小数点には +0 と −0 が両方存在します
  • 3.5 は 1.75 × 21。1.75 = 1 + 1/2 + 1/4 なので仮数の先頭が 11
  • 0.1 は 1.6 × 2−4。指数欄は 1023 − 4 = 1019 = 01111111011

そして 0.1 の仮数の末尾に注目してください。

stored = bits64(0.1)[12:]
ideal = "1001" * 13
print(ideal)
print(stored)
print(int(stored, 2) - int(ideal, 2))
1001100110011001100110011001100110011001100110011001
1001100110011001100110011001100110011001100110011010
1

52ビット目が1つ繰り上がっています。 切り捨てれば「…1001」で終わるはずのところが「…1010」になっている。これが最近接丸めの現場です。0.1 が本物より少し大きくなる理由は、このたった1ビットです。

再構成もできます。

from fractions import Fraction
b = bits64(0.1)
E = int(b[1:12], 2)
F = int(b[12:], 2)
val = Fraction(2**52 + F, 2**52) * Fraction(2)**(E - 1023)
print(val)
print(Fraction(0.1) == val)
3602879701896397/36028797018963968
True

ビットから手で組み立てた分数が、Python の言う 0.1 の正体と完全に一致しました。 ここまで来れば、浮動小数点数はもうブラックボックスではありません。

4-6. 有効桁数が一定であることの確認

import math, sys
print(sys.float_info.dig, sys.float_info.epsilon)
print(sys.float_info.max, sys.float_info.min)
for e in [0, 3, 10, 16, 300]:
    v = 10.0**e
    print(e, math.ulp(v), math.ulp(v)/v)
15 2.220446049250313e-16
1.7976931348623157e+308 2.2250738585072014e-308
0 2.220446049250313e-16 2.220446049250313e-16
3 1.1368683772161603e-13 1.1368683772161603e-16
10 1.9073486328125e-06 1.9073486328125e-16
16 2.0 2e-16
300 1.487016908477783e+284 1.487016908477783e-16

右端の列(刻み ÷ 値)が、どの桁でも 1〜2 × 10−16 でそろっています。 これが「有効桁数は一定」の正体です。刻みの絶対的な大きさは 10−16 から 10284 まで300桁も変わるのに、値に対する比率だけは変わりません

2−52 = 2.220446049250313×10−16 であり、これが sys.float_info.epsilon(1 の次に表せる数までの距離)と一致します。仮数52ビットという設計が、そのまま「約16桁」という数字になって出てきます。

4-7. では実務ではどうするのか

情報Ⅰの教材が「誤差を起こさない方法を考えてみましょう」と問うている以上、答えまで書きます。

対策1:金額は整数(円単位)で持つ。

これが最も確実で、最も広く使われています。小数を使わなければ、小数の誤差は原理的に起きません。

print(10 + 20 == 30)
print(sum([1, 2, 3] * 1000))
True
6000

1円未満を扱う必要があるなら、単位を変えます。「0.01円単位で持つ」と決めれば 1.01円は整数 101 になり、整数演算だけで完結します。教材の「整数にして計算し、計算した結果を小数にする」がまさにこれです。

JPCERT コーディネーションセンターが公開している Java コーディングスタンダードにも、NUM04-J「正確な計算が必要なときは浮動小数点数を使わない」というルールがあります(最終更新 2026年1月27日)。そこでも「金額をドルではなくセント単位の整数で表現する」ことが対策として挙げられています。高校の教材が示す方向と、業界の規約が示す方向は同じです。

対策2:10進の小数をそのまま扱う型を使う。

from decimal import Decimal
print(Decimal('0.1') + Decimal('0.2') == Decimal('0.3'))
True

Python の Decimal は10進のまま計算します。ただし引数を文字列で渡すことDecimal(0.1) と書いたら、float に変換された時点でもう壊れています。速度は float より遅いので、大量の数値計算には向きません。

対策3:小数どうしを == で比較しない。 差の絶対値がしきい値以下かで判定します。

import math
print(abs((0.1 + 0.2) - 0.3))
print(abs((0.1 + 0.2) - 0.3) < 1e-9)
print(math.isclose(0.1 + 0.2, 0.3))
5.551115123125783e-17
True
True

対策4:計算の順序を変える。 4-4 で見たとおり、小さい数から先に足す、引き算の形を変える。式を変えずに精度が戻る場面は多いのです。

対策5:桁落ちしそうな引き算を、そもそも作らない。 「ほぼ等しい2つを引く」形が式に出てきたら、有理化・因数分解などで別の形に書き換えられないかを疑ってください。

5. 共通テストではこう出る(重要度A)

浮動小数点誤差は、共通テスト「情報Ⅰ」で単独の大問にはなりにくいが、プログラムの読み取りや小問集合で顔を出す位置にあります。第40講(基数変換)が重要度Sなのに対して本講がAなのは、この違いによります。ただし出れば必ず差がつきます。理由を知らないと、「プログラムが間違っている」と誤診して手が止まるからです。

なお、当塾では共通テストの問題文・選択肢・図表・プログラムは転載していません。以下は設問構造の整理です。

出題の3つの型

型1:誤差が生じる理由を問う型
「なぜ計算結果が期待どおりにならないか」を選ばせます。正解の芯は「有限のビット数では表せない小数があるから」の一点です。選択肢には「プログラムの書き方が間違っている」「変数の初期化を忘れている」といった、もっともらしい別原因が混ぜられます。原因が2進表現にあると言い切れるかどうかで決まります。

型2:計算結果が予想と違う理由を選ばせる型
ループで小数を足し込むプログラムを見せて、終了条件が「= 1.0 になったら止まる」になっているためにループが止まらない/1回多い/1回少ないという結果を読ませます。対策は「等号ではなく、しきい値や不等号で判定する」。トレース(第54講)と組み合わさると難度が上がります。

型3:有効桁数・精度を扱う型
「この計算で信用してよい桁はどこまでか」「どちらの計算順序が正確か」を判断させます。桁落ち・情報落ちという名前は出ませんが、現象としては出ます(名前が高校の一次資料に無いので、名前では問えないのです)。「大きい数と小さい数を足す順序」「ほぼ等しい数の引き算」という形で現れます。

落とし穴

  • 「誤差=プログラムのバグ」と考えてしまう。 誤差はバグではなく仕様です。エラーも例外も出ません。黙って少し違う値が返ります
  • 整数の話と混同する。 第41講のオーバーフロー(整数が範囲を超えて符号ごと化ける)と、本講の丸め誤差(小数が最初から表せない)は別の現象です。問題文が整数の話か小数の話かを必ず確認します
  • 「0.1 は表せないが 0.5 も表せない」と誤解する。 0.5・0.25・0.125 はぴったり表せます。分母が2の累乗かどうかで決まります
  • 小数どうしを等号で比べる。 本試験でも実務でも最頻出の事故です
  • 「Python だから起きる」と思ってしまう。 表計算ソフトでも同じです。表示が丸められて見えないだけです
  • 打ち切り誤差を丸め誤差と混ぜる。 打ち切り誤差はアルゴリズム由来で、精度を上げても消えません

練習用の自作問題(本記事オリジナル)

  1. 次の10進小数のうち、2進数の有限小数でぴったり表せるものをすべて選べ。(ア) 0.5 (イ) 0.1 (ウ) 0.75 (エ) 0.2 (オ) 0.125
  2. 0.1 を2進小数に変換する筆算を4桁目まで行い、循環が始まる位置を答えよ。
  3. x = 0.0 から始めて x += 0.1 を10回繰り返した後、x が 1.0 に等しいと判定されるか。理由も述べよ。
  4. 1016 に 1 を足しても値が変わらないのはなぜか。この現象の名前を答えよ。
  5. ほぼ等しい2つの数の引き算で有効桁が失われる現象の名前を答えよ。また対策を1つ挙げよ。
  6. 商品の税込価格の合計を求めるプログラムで、1円のずれが出ないようにするための設計を1つ挙げよ。
解答

  1. (ア) 0.5、(ウ) 0.75、(オ) 0.125。 既約分数の分母がそれぞれ 2, 4, 8 で2の累乗。(イ) 0.1 = 1/10 と (エ) 0.2 = 1/5 は分母に 5 を含むので表せない
  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.0001…。5回目で小数部が 0.2 に戻り、2桁目から循環が始まる(循環節「0011」、長さ4)
  3. 等しいと判定されない。 実際の値は 0.9999999999999999。0.1 は厳密には格納できず、10回の足し算で丸めが10回起き、ずれが残る
  4. 1016 の付近では隣り合う表せる数の間隔が 2 であり、1 は仮数の欄に入りきらず捨てられるから。情報落ち
  5. 桁落ち。 対策は式を有理化するなどして「ほぼ等しい数の引き算」の形を避ける(または高精度な型を使う)
  6. 金額を円単位の整数で保持する(1円未満を扱うなら 0.01円単位の整数にする)。ほかに Decimal 型を使う、なども可

6. 情報Ⅱではこうなる

情報Ⅰで「誤差」はコンピュータが持てないビットの話でした。情報Ⅱに入ると、この語の指すものが入れ替わります。ここが本講で最も面白いところです。

6-1. 「誤差」という語の意味が入れ替わる

3-7 の語数調査をもう一度見てください。情報Ⅱ 教員研修用教材の全文に「誤差」は 16回出ます。情報Ⅰ(27回)より少ないものの、決して珍しい語ではありません。ところが、その16回を1件ずつ読むと、浮動小数点誤差の話は1件もありません。 中身はこうです(当方で全件を確認、2026年8月3日)。

情報Ⅱ教材に出る「誤差」 どこ 意味
許容誤差 第3章 学習12(標本の大きさ) 標本調査で許す推定のぶれ
標準誤差 第3章 学習13(重回帰分析) 残差の自由度を調整した標準偏差
クラスタ内誤差の平方和(SSE) 第3章 学習16(k-means) クラスタの代表点からの距離の2乗和
2乗和誤差・交差エントロピー誤差 第3章 学習17(ニューラルネットワーク) 損失関数。予測と教師データのずれ
誤差逆伝播法 第3章 学習17 出力の誤差を重みの修正に使う手法
情報Ⅰの「誤差」は、正しい答えがあるのに機械が持てない分のずれ。
情報Ⅱの「誤差」は、モデルが現実を説明しきれていない分のずれ。

前者は減らすべき欠陥ですが、後者はそもそも 0 にしてはいけません第88講(回帰直線)で見たとおり、残差を 0 にしたモデル(データ2人分に直線を当てはめる等)は残差の自由度が 0 になり、新しいデータへの予測力を失います。情報Ⅱ教材は「これらのモデルでは,残差の自由度は 0 となり,標準誤差は無限大となり計算できない。つまり,新しいデータに対して予測力がまるでないことになる」と明記しています。

同じ2文字が、片方では潰す対象、もう片方では残しておく対象になる。 用語をそのまま持ち越すと必ず混乱する場所であり、私はここを毎年ていねいに切り分けています。

6-2. 型の選択が「生徒の作業」になる

情報Ⅱ 教員研修用教材 第3章 学習11「データと関係データベース」には、関係データベースで使うデータ型の一覧があります。

データ型 用途
Char(固定長)/varchar(可変長) Abc 文字,文字列を表す
String(text) Abc 文字列を表す
Int 1, 2, 3 整数を表す
Real(Double, Float) −0.2, 3.4 実数(または浮動小数点数)を表す
Object(blob) 図,音声などのデータ

文部科学省「高等学校情報科『情報Ⅱ』教員研修用教材」第3章 前半(令和2年)図表2「RDBで使われるデータ型の例」

情報Ⅱ教材の中で「浮動小数点」という語が出てくるのは、実質この1か所だけです。 そして注目すべきは、その隣の演習です。

小テストのデータを表形式に格納する際に必要なヘッダーとその型を挙げてみましょう。——同上 演習3

型を決めるのが生徒の仕事になっています。 情報Ⅰでは float は言語が用意した箱でしたが、情報Ⅱではテーブルを設計する人間が Int と Real のどちらを選ぶかを決めます。そして本講で見たとおり、Real を選んだ列に入った値は、格納された時点でもう厳密ではありません。 点数を Real で持てば、平均が 60 点ぴったりでも「= 60」の判定は偽になりえます。金額を Real で持てば、合計が1円ずれます。

同じ教材は、テーブル設計の目的をこう書いています。

データベースの構造であるスキーマや各列の値の種類を示す型(一例を図表2に挙げている)が分かりやすいように指定する。——同上

型は「機械のための指定」ではなく「人がデータの意味を読めるようにするための指定」だ、と教材は言っています。この立場に立つと、Int と Real の選択は精度の問題であると同時に、「この列は数えるものか、測るものか」という意味の宣言になります。人数・個数・点数は数えるもの(Int)、身長・秒・温度は測るもの(Real)。第80講(データの種類と尺度)の話と、ここでつながります。

6-3. 「単位の変換」が学習内容として名指しされている

情報Ⅱ 教員研修用教材 第3章 学習12「大量のデータの収集と整理・整形」の【研修の目的】には、こう書かれています。

データの形式の変換やデータの単位,欠損値や外れ値の処理を行う方法について理解し,目的に応じたデータを整形・整理する知識や技能を生徒に身に付けさせる授業ができるようになる。——文部科学省「高等学校情報科『情報Ⅱ』教員研修用教材」第3章 前半(令和2年)

「データの単位」を変換する技能。 本講 4-7 の「金額を円単位の整数で持つ」「0.01円単位に変える」は、まさに単位の変換です。情報Ⅰでは誤差回避のテクニックだったものが、情報Ⅱでは前処理の正式な工程になります。

学習指導要領解説の情報Ⅱ(3)ア(ア)も同じことを言っています。

データの種類や単位,データの値の意味,データの収集や整理,整形する方法について理解し,必要な技能を身に付けるようにする——文部科学省「高等学校学習指導要領(平成30年告示)解説 情報編」平成30年7月

6-4. 統計計算・機械学習で誤差は蓄積する

本講 4-4 で見たとおり、丸め誤差は足すたびに積み上がります。ここが情報Ⅱで効いてきます。

情報Ⅱ教材のアルゴリズムは、どれも「たくさん足す」構造をしています。分散も標準偏差も相関係数も、二乗和の足し込みです。k-means の SSE はクラスタ内の全点の距離の2乗和であり、教材は「代表点の位置が変わっていたら 2 に戻る」と収束するまで繰り返す手続きを示しています。ニューラルネットワークの学習は、損失関数の値を見ながら重みを何万回も更新します。足し込みの回数が多いほど、丸めの回数も多くなります。

さらに、標準化(基準化)の式「z =(x − 平均)÷ 標準偏差」には引き算が入っています。値が平均の近くに密集しているデータでは、x − 平均 が桁落ちの形そのものになります。教材は「単位が異なる複数の変数を扱う場合は基準化を行い、単位をそろえる必要がある」と書いており、主成分分析や k-means の前段でこれを必ず通します。情報Ⅰで学んだ桁落ちが、情報Ⅱの前処理の中に埋まっているのです。

ただし、正確を期しておきます。情報Ⅱの教員研修用教材そのものは、この誤差の蓄積については書いていません(「丸め」「浮動」「有効桁」の語数はいずれも 0〜1 回です)。教材は表計算ソフトや R・Python のライブラリを使わせる立場をとっており、誤差の管理はライブラリの内側に置かれています。「教材に書いてあること」と「その先で実際に起きること」を、私は主語を分けて書いています。 ここを混ぜると、本書の信頼性が落ちるからです。

6-5. 「型」という語の居場所(一次資料の空白)

最後に、調べていて驚いたことを書いておきます。

学習指導要領解説 情報編の共通教科の部分(情報Ⅰ・情報Ⅱ)に、「データの型」という語は実質1回も出てきません。 唯一のヒットは情報Ⅰの「データの型式に関しては、表形式以外の時系列データ、SNS…」という文で、これはファイル形式の意味であって int / float の型ではありません。情報Ⅱ(3) と (4) の本文には、「型」という漢字が 0回です(当方で全文検索、2026年8月3日)。

では「データの型」はどこに書かれているのか。同じ解説の、専門教科情報科の側です。専門学科向けの科目「情報システムのプログラミング」の〔指導項目〕(2)「データ構造とアルゴリズム」ア「データの型」に、14回まとまって出てきます。そしてそこには、こう書かれています。

データの型として数値型,文字型及び論理型を取り上げ,データの型の違い,データの型を定める必要性,…データの型の違いによる数値の精度やメモリへの影響,保存時のデータ容量や計算速度の違いなどについて扱う。その際,具体的な事例を通して,扱うデータに適したデータの型を選択できるようにする。——文部科学省「高等学校学習指導要領(平成30年告示)解説 情報編」平成30年7月(専門教科情報科の科目「情報システムのプログラミング」)

「データの型の違いによる数値の精度」。 本講が扱ってきたことが、そのままの言葉で書かれています。ただし置かれている場所は、普通科の生徒が習う情報Ⅰ・情報Ⅱではなく、情報科を専門とする学科の科目です。

第41講は「2の補数は解説にも情報Ⅰ教材にも無く、IPA のシラバスにある」と書きました。本講で見つかった空白も同じ構造ですが、行き先が2つに分かれています。誤差の種類の名前は IPA のシラバスへ、型と精度の関係は専門教科の科目へ。 普通科で情報Ⅰだけを学ぶ生徒にとって、この単元は制度上、名前を教わらないまま現象だけに遭遇する場所なのです。だからこそ、原理から理解しておく価値があります。

6-6. 情報Ⅰと情報Ⅱの扱いの違い

観点 情報Ⅰ 情報Ⅱ
「誤差」の意味 機械が持てないビット。減らすべきもの モデルと実測のずれ。0 にしてはいけないもの
小数の型 言語が用意した float。与件 RDB の Real か Int かを自分で選ぶ設計判断
単位 与えられたまま計算する 「データの単位」の変換が前処理の正式な工程
誤差への態度 起こさない方法を考える(教材の演習3) 前処理とモデル評価の一部として管理する
目的 「なぜ壊れるか」を理解する 「壊れないデータ設計」を決める

7. まとめ

  • 2進数の有限小数で書けるのは、既約分数の分母が2の累乗である分数だけ。0.1 = 1/(2×5) は分母に 5 があるので書けない
  • 10進で 1/3 が循環するのと同じ構造。0.1 は2進で「0.0」のあと「0011」が無限に循環する
  • 表せないので最も近い数に丸める。0.1 の実体は 0.1000000000000000055511151231257827021181583404541015625
  • 固定小数点は「大きい数では小数部が足りず、小さい数では整数部が無駄」で破綻する。指数で小数点の位置を持つのが浮動小数点
  • 見返りは範囲の広さ、代償は有効桁数がどこでも一定(倍精度で約16桁)
  • 誤差は4種類。丸め誤差(表せない)・桁落ち(近い数の引き算)・情報落ち(桁違いの数の足し算)・打ち切り誤差(有限回で止めた)
  • 桁落ちと情報落ちは計算の順序や式の形を変えるだけで改善する
  • 実務では、金額は整数(円単位)で持つ/Decimal を使う/等号ではなく差の絶対値で比較する
  • 学習指導要領解説に「誤差」は1回のみ。丸め誤差・桁落ち・情報落ち・有効桁数は高校の一次資料に0回で、IPA のシラバスにだけある(2026年8月時点)
  • 情報Ⅱでは「誤差」の意味が入れ替わり、型と単位の選択が設計判断になる

出典(すべて2026年8月3日に取得)

  • 文部科学省「高等学校学習指導要領(平成30年告示)解説 情報編」平成30年7月
  • 文部科学省「高等学校情報科『情報Ⅰ』教員研修用教材」第3章 コンピュータとプログラミング(令和2年7月)
  • 文部科学省「高等学校情報科『情報Ⅱ』教員研修用教材」第3章 情報とデータサイエンス 前半・後半(令和2年)
  • 情報処理推進機構(IPA)「基本情報技術者試験(レベル2)シラバス Ver.9.2」(掲載 2026年1月8日)
  • JPCERT コーディネーションセンター「Java コーディングスタンダード NUM04-J. 正確な計算が必要なときは浮動小数点数を使わない」(最終更新 2026年1月27日)

本書『藤原進之介の最強120講義』の全講一覧は情報Ⅰ 最強120講義(目次)に、公開済みの記事はカテゴリ「情報Ⅰ 最強120講義」にまとめています。デジタル化そのものの考え方は第32講「アナログとデジタル」で扱いました。制度に関する記述は2026年8月時点の情報です。

執筆:藤原進之介(数強塾グループ代表)

オンライン数学専門塾「数強塾」代表。累計3,500名以上の中高一貫校生を指導。東進ハイスクール・東進衛星予備校・代々木ゼミナールなど出講実績あり。情報Ⅰの参考書を複数執筆しており、KADOKAWA『ゼロから始める情報I』、Gakken『きめる!共通テスト 情報Ⅰ』などがあります。本記事は参考書『藤原進之介の最強120講義』第42講のWeb版です。

藤原進之介のプロフィールを見る

「情報Ⅰ、独学でいけるのか不安」という方へ

数強塾では数学と情報Ⅰの両方に対応したオンライン個別指導を行っています。学習相談は無料、体験授業は3,000円(税込)でお受けしています。

体験授業のご案内つまずき診断(無料・約2分)

情報Ⅰ・情報Ⅱの勉強で詰まっていませんか

この記事を書いているのは、情報Ⅰ専門のオンライン個別指導「情報ラボ」(数強塾グループ)です。講義も過去問も無料で公開しているので、まず全部使ってみてください。

情報Ⅰについて相談する(無料)体験授業(3,000円)

お問い合わせの際は、内容欄に「情報Ⅰ希望」とご記入ください。担当者が直接お返事します。

数強塾オンラインのご案内

体験授業に申し込む入塾受け入れ状況(残席)数学つまずき診断(無料)体験授業の事前案内保護者の方へ高1・高2の方へ医学部志望の方へ保護者様からの声料金・指導システム指導事例・合格実績大学受験 合格実績(集計ルール開示)数強塾グループの理念学校別の数学対策数学の勉強法(記事一覧)数強塾プレミアム(映像授業)獣医学部専門コース鉄緑会・SAPIX等との併用サポート過去問解説・数学問題集情報Ⅰ・情報Ⅱ専門「情報ラボ」情報の過去問アーカイブ(無料PDF)解法テクニック事典(公式・裏ワザ)入試数学の定石(解き方の型・全27章)2026年 夏期講習会2026年 冬期講習会代表・藤原進之介について