仕組みを知る

0.1+0.2が0.3にならない?保存した数と表示の小さなずれ

Pythonで0.1+0.2を計算すると、0.30000000000000004と表示されることがあります。二進数での近似、保存した値、丸めた表示の違いを、小さな模型と見比べる教材で確かめます。

0.1+0.2が0.3にならない?保存した数と表示の小さなずれ

イトとピコが、目盛りの間にある印を見つめるイメージイラスト

30秒でわかる答え

0.1+0.2が0.3にならない?

0.1や0.2は、二進数の限られた桁ではぴったり保存できず、少し違う近い値になります。その値で計算するため、結果も数学上の0.3とずれることがあります。表示の桁を減らしても、保存済みの値は変わりません。

TERM PRIMER

0.1+0.2の誤差|先に知っておく言葉

ビット
コンピューターが扱う情報の最小単位。0か1のどちらかを表します。
二進数
0と1の二つを使って数を書く方法です。0、1の次は10と書き、これはふだんの数え方では2を表します。

0.1や0.2は、二進数の限られた桁ではぴったり保存できず、少し違う近い値になります。その値で計算するため、結果も数学上の0.3とずれることがあります。表示の桁を減らしても、保存済みの値は変わりません。

紙の上なら、0.1+0.2は0.3です。ところがPythonで同じ式を試すと、末尾に小さな数字が付くことがあります。

>>> 0.1 + 0.2
0.30000000000000004

足し算の決まりが変わったのでしょうか。手がかりは、足す前の 0.1 が、コンピューターの中でどんな値になっているかです。この記事の実行例は、CPython 3.14.6/arm64、2進・53ビット精度の float で確認しています。

二進数では、0.1を書き終えられない

日常使う十進数でも、1÷3を小数で書くと 0.333… と続きます。二進数にも、有限の桁では書き終えられない小数があります。その一つが、十進数の0.1です。

二進数の小数部分は、左から 1/2、1/4、1/8、1/16……の位になります。0.5なら 1/2 一つなので、二進数では 0.1。一方、十進数の0.1は、二進数では 0.0001100110011… と続きます。 同じ「0.1」という見た目でも、十進数と二進数では値が違う点に注意してください。

保存に使える桁数には限りがあります。書き終わらない小数をそのまま全部保存できないので、表せる値のうち近いものを選びます。粗い目盛りで、その様子を見てみます。

小数部分を二進数4桁に限った模型0から0.25を等間隔で表示。0.1は0.0625と0.125の間にあり、0.125の方が近い。これは実際のbinary64とは異なる粗い模型。AC00.25B
A
0.0625
B
0.1
C
0.125
小数部分を二進数4桁に限った模型。目盛りの幅は1/16です。0.1は目盛りの間にあり、近い方へ丸めると0.125になります。実際のPythonの float は、これよりずっと細かく値を表せます。

この模型では0.1を0.125に丸めましたが、実際の float がここまで大きくずれるわけではありません。Pythonの今回の環境では、0.1は次の値として保存されました。長い数字を覚える必要はなく、0.1より少し大きいところだけ見てください。

0.1000000000000000055511151231257827021181583404541015625

有効な数字の部分と、小数点の位置を動かす情報を組み合わせて数を表す方式を「浮動小数点」といいます。ここで扱うのは二進数を使う方式です。大きな数も小さな数も扱えますが、あらゆる小数をぴったり表せるわけではありません。模型の目盛りは等間隔ですが、実際の浮動小数点で隣り合う値の間隔は、値の大きさによって変わります。

保存した値が違っても、画面には0.1と出せる

ここで、少し不思議なことが起こります。Pythonで 0.1 をそのまま表示すると、長い数字ではなく、いつもの 0.1 が出ます。

>>> 0.1
0.1

通常の表示では、保存した値を十進数で最後まで書き出すとは限りません。短く表示しても、読み戻したときに同じ float の値になる表し方が選ばれます。つまり、画面の「0.1」は、保存した値の全桁を見せたものではないのです。

「保存するために近い値を選ぶこと」と「画面に出す桁を絞ること」は別の処理です。足し算で末尾が見えてくる理由も、この二つを分けると追いやすくなります。

0.1+0.2と0.3を、保存した値で比べる

0.1 だけでなく、0.2 も近い値として保存されます。その二つを足し、結果を保存できる値に丸めると、今回の環境では 0.30000000000000004 と表示される値になりました。

では、最初から 0.3 と入力した値はどうでしょう。これもぴったりの3/10ではなく、少し小さい値になります。二つはとても近いのですが、同じではありません。

>>> x = 0.1 + 0.2
>>> y = 0.3
>>> x == y
False

== は「保存した二つの値が等しいか」を調べます。False は「等しくない」という結果です。人が小数点以下1桁だけを見れば同じ0.3に見えても、この比較では違いが残ります。

表示をそろえたら、同じ値になる?

二つの値を保存してから、表示のしかただけを変えます。

保存した計算・入力

0.1 + 0.2

通常の表示

0.30000000000000004

保存した計算・入力

0.3

通常の表示

0.3
両方を小数点以下1桁で表示する
format(x, '.1f')0.3
format(y, '.1f')0.3

見た目はどちらも 0.3。でも、保存済みの x と y は書き換わっていません。

x == y の結果は False(同じ値ではない)のままです。

保存した値を、十進数で省略せずに見る
x の値
0.3000000000000000444089209850062616169452667236328125
y の値
0.299999999999999988897769753748434595763683319091796875

数字は折り返して表示しています。途中を省略していません。

CPython 3.14.6 / arm64、2進・53ビット精度の float で確認した結果です。ブラウザ内でPythonを実行する教材ではありません。

短い表示に変えると、見た目の末尾は消えます。でも、表示だけを変えても、元の値の違いは消えません。 どこまで近ければ同じとみなすかは、計算の目的に合わせて別に決めることです。小数点以下を隠せば、どんな比較も解決するというわけではありません。

すべての小数で、同じずれが出るわけではない

二進数で有限の桁に収まる小数もあります。0.5は1/2、0.25は1/4なので、今回の float では正確に表せます。足した0.75も3/4として正確です。

>>> 0.5 + 0.25
0.75

「コンピューターは小数を間違える」とまとめるより、「使う数の表し方によって、ぴったり保存できる数と、近い値になる数がある」と考えると、二つの例を一緒に説明できます。

計算結果を使うときは、何をそろえたいかで選ぶ

末尾の数字を見つけたら、まず表示だけを整えたいのか、値を比較したいのかを分けます。

したいことPythonで調べる手段気をつけること
小数点以下1桁で見せるformat(x, '.1f')表示用の文字列になる。元の値は変わらない
二つの値が十分近いか比べるmath.isclose(x, y)許容する差は、計算の目的に合わせて決める
十進数や分数として計算するdecimal、fractions数を入力する段階から、その方式を使う

詳しい使い方は、Python公式の浮動小数点の説明から各機能へ進めます。丸め方を一つ覚えてすべてに当てはめるより、何のための数かを先に考えることが大切です。

誰かに理由を聞かれたら、こんなふうに言えます。「0.1は二進数では終わらないから、近い値を保存するんだ。その値で計算して、最後に見やすい桁数で表示しているんだよ」。

では、使える0と1の桁を増やすと、表せる組み合わせはどう増えるのでしょう。ビットの組み合わせを試す記事では、スイッチを増やしながら確かめられます。

LAB WHITEBOARD

0.1+0.2の誤差を一文で説明してみよう

「小数を近い値で保存することと、表示する桁を減らすことを分けて説明できる。」を、いまの自分の言葉で一文にしてみてください。途中の説明でも大丈夫です。

0.1+0.2の誤差の参考資料

  • 浮動小数点演算、その問題と制限(Python Software Foundation、2026-10-16閲覧)

内容の最終確認日: