これは何?
コンピュータを使った計算を行うと,実際の計算と異なる結果が得られることがあります。
これはコンピュータが有限ビット数を使って計算している関係上,特定の数値を完全に表現することはできません。
例えば,1/3は数学では正しく表現できますが,コンピュータでは0.3333333333333333333333333333333...と表現するため,有限の値で表現されます。
本記事ではよく発生する浮動小数点の誤差についてまとめました。
丸め誤差(round error)
計算と誤差
コンピュータは、10進数を2進数になおして記憶する。このとき、小数点以下を含む10進数は、2進数に変換される時に変換誤差を生ずる。これが丸め誤差という。
具体例をpythonで書いてみました。pythonのfloat型では扱える小数点の数は15桁となっているので丸め誤差を発生させてみます。
print((1.3 + 1.6) / 2) # 発生しない例
print((1.000000000000003 + 1.000000000000006) / 2)
print((1.0000000000000003 + 1.0000000000000006) / 2)
1.4500000000000002
1.0000000000000044
1.0000000000000004
このように,本来.45まで表示されるはずが,丸め誤差が発生していることがわかります。
情報落ち(loss of trailing digit)
コトバンク
情報落ち誤差(読み)ジョウホウオチゴサ
デジタル大辞泉 「情報落ち誤差」の意味・読み・例文・類語
じょうほうおち‐ごさ〔ジヤウホウおち‐〕【情報落ち誤差】
コンピューターの浮動小数点演算で、絶対値が大きい数値と小さい数値の加算・減算をした時に、絶対値の小さい数値が無視されてしまう現象。有効桁数が限られた仮数部の演算で生じる。
print(1.3 + 0.01) # 発生しない例
print(1.3 + 0.0000000000000001)
1.31
1.3
実際には1.30000000000000001となってほしいところが
1.3になってしまいました。
桁落ち(cancellation)
計算と誤差
有効数字のうち、大きい方がそろっている2つの数を引いてしまうと、結果の有効数字が極端に少なくなる。
print(1.01 - 1.00) # 発生しない例
print(1.000000000000001 - 1.000000000000000)
0.010000000000000009
1.1102230246251565e-15
Overflow,Underflow
使用できる数値の上限,下限を超えたものを扱った際に発生します。
import sys
# オーバーフロー
print(f"max float ={sys.float_info.max}")
print(sys.float_info.max * 2)
# アンダーフロー
print(f"min float ={sys.float_info.min}")
print(sys.float_info.min * 0.000000000000001)
print(sys.float_info.min * 0.0000000000000001)
max float =1.7976931348623157e+308
inf
min float =2.2250738585072014e-308
2.5e-323
0.0
オーバーフローでは値が無限(infinity)になり,アンダーフローでは0.0になってしまうのがわかります。
まとめ
コンピュータをつかった計算をする際には誤差が発生する可能性があるのでそのことを認識した上で計算を実施する必要がある。