🐜

Pythonで学ぶマシンイプシロン

2023/10/20に公開

はじめに

みなさんは「マシンイプシロン」または「計算機イプシロン」を知ってますか?
勉強中にマシンイプシロンを知り、少し仲良くなれたので記事にまとめてみました!

マシンイプシロンの定義

まずはマシンイプシロンの定義です。Wikipediaの引用です。

計算機イプシロン(けいさんきイプシロン、英: machine epsilon)は、浮動小数点数において、「1より大きい最小の数」と1との差のことである。

Pythonのドキュメントには下記のように書かれていました。

1.0 と、それより大きい表現可能な最小値との差

なんの役に立つのか?

マシンイプシロンこと「1より大きい最小の数」はなんの役に立つのでしょうか?
定義だけではイメージしにくいので、活用例のプログラムを書いていきます。

Pythonでマシンイプシロンを確認

まずはマシンイプシロンを出力してみます。
Pythonでは、標準ライブラリsys.float_infoで定義されている値を呼び出し可能です。

>>>import sys
>>>print(sys.float_info.epsilon)  
2.220446049250313e-16

>>> type(sys.float_info.epsilon) 
<class 'float'>

値は2.220446049250313e-16(0.000000000000000220446...)
型はfloatのようです!

浮動小数点の一致判定プログラム

下記がマシンイプシロンの活用例です。
2つの浮動小数点型変数が同じ値か判定しています。

x = 1.0
y = 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1

print(x == y) # False

print(f"x is {x}") # x is 1.0
print(f"y is {y}") # y is 0.9999999999999999

print(abs(x - y) <= sys.float_info.epsilon * max(abs(x),abs(y))) # True

プログラムの簡単な解説です。
変数xには1.0を、変数yには0.1を10回加算した値を代入しました。
両方1になると思いますが、イコールでの比較結果がFalseになっています。
数値を出力してみると、yが0.99...になっています。

このような誤差が発生しても、極々微小な差であれば同一の値と判定したいので
2つの数字の差とマシンイプシロンを比較しています。

なぜ0.99...になってしまうのか

この現象は数値計算の際に、10進数の0.1を2進数に変換する影響で発生しています。
pythonのfloatは多倍長浮動小数点型で、64bitで浮動少数点数を表しているので、
2進数では0.1を表現できず、ちょうど良い数字にならないため丸め誤差が発生してしまいます。
ざっくりかみ砕くと、限りなく0.1に近い別の数字を10回加算して0.99...になったという現象です。

おまけ:Pythonでマシンイプシロンを求めてみる

おまけでマシンイプシロンを求めるプログラムも書いてみます。

my_epsilon = 1
while my_epsilon + 1 != 1 :
    my_epsilon /= 2
print(my_epsilon*2) #2.220446049250313e-16

1に加算して変化しなくなるまで除算して行くと、無事にイプシロンを求めることができました。
Python以外の言語でもライブラリから参照できることが多いですが、
いつかどこかで役にたつかもしれません...!

最後に

普段は意識しないマシンイプシロンですが、調べて、触ってみて面白さを実感しました!
特に浮動小数点型の誤差・仕様については使える場面が多いと思います。

学習にあたって情報収集していた時に、マシンイプシロンの定義を間違えている記事を多く見かけました。
1.0ではなく、0より大きい最小の数値では意味合いが変わってしまうので注意しましょう。

計算機イプシロンは「最小の(正の)浮動小数点数」ではありません。

計算機イプシロンは,しばしば「浮動小数点で表せる0より大きい最小の数」と誤解されます。
もしこのような定義だと,指数部分を小さくすることで仮数部分の精度に関係なく小さな値を表現できてしまうことになります。

参考記事

深く学習したい方に、下記の記事をオススメします。ぜひご一読ください。
https://zenn.dev/mod_poppo/articles/floating-point-relative-error

https://docs.python.org/ja/3/library/sys.html?highlight=epsilon#sys.float_info.epsilon

GitHubで編集を提案

Discussion