コンピュータで小数を扱う場合、内部的には2進数で表現されるため、どうしても微細な「計算誤差」が発生します。そのため、浮動小数点数(float)同士を == 演算子で比較すると、人間が期待する結果にならないことがあります。
Python 3.5以降では、この問題を解決するために標準ライブラリ math モジュールに isclose() 関数が追加されました。
この記事では、浮動小数点数の比較で発生する問題点と、math.isclose() を使った正しい比較方法について解説します。
浮動小数点数の比較における問題点
まずは、単純な足し算の結果を比較してみます。0.1 + 0.2 は 0.3 になるはずですが、Python(および多くのプログラミング言語)では False と判定されます。
# 0.1 + 0.2 を計算
calc_result = 0.1 + 0.2
expected_value = 0.3
print(f"計算結果: {calc_result}")
print(f"期待値: {expected_value}")
# 等価演算子 (==) で比較
is_equal = (calc_result == expected_value)
print(f"厳密な比較 (==): {is_equal}")
実行結果:
計算結果: 0.30000000000000004
期待値: 0.3
厳密な比較 (==): False
計算結果が 0.30000000000000004 となり、0.3 とはわずかに異なるため、等価判定は False になります。これが浮動小数点数の誤差による問題です。
math.isclose() による解決
math.isclose() 関数は、2つの値が「十分にに近い(許容範囲内である)」かどうかを判定します。これにより、微細な誤差を許容して「実質的に等しい」とみなすことができます。
構文:
import math
math.isclose(a, b, rel_tol=1e-09, abs_tol=0.0)
基本的な使い方
先ほどの例を math.isclose() で書き換えます。
import math
val_a = 0.1 + 0.2
val_b = 0.3
# isclose で比較
is_close = math.isclose(val_a, val_b)
print(f"math.isclose による比較: {is_close}")
実行結果:
math.isclose による比較: True
デフォルトの設定でも、一般的な計算誤差を吸収して True(等しい)と判定されます。
許容誤差(トレランス)の設定
math.isclose() は、どの程度の誤差まで許容するかを引数で細かく制御できます。
1. 相対誤差 (rel_tol)
rel_tol (relative tolerance) は、入力値の大きさに対する割合(パーセンテージのようなもの)で許容誤差を指定します。デフォルトは 1e-09(10億分の1)です。
import math
target = 100.0
# 100.0 に対して 0.1 の誤差がある値
value = 100.1
# 1% (0.01) の誤差まで許容する設定
is_close_loose = math.isclose(value, target, rel_tol=0.01)
# 0.01% (0.0001) の誤差しか許容しない設定
is_close_strict = math.isclose(value, target, rel_tol=0.0001)
print(f"許容誤差 1%: {is_close_loose}") # True
print(f"許容誤差 0.01%: {is_close_strict}") # False
2. 絶対誤差 (abs_tol)
abs_tol (absolute tolerance) は、値の大きさに関わらず、固定の数値差を許容します。0に近い非常に小さな数値を比較する場合に有効です。デフォルトは 0.0 です。
import math
near_zero_a = 0.00001
near_zero_b = 0.00002
# 相対誤差だけでは 0付近の比較がうまくいかない場合があるため
# 絶対誤差として 0.0001 以内のズレなら許容するよう設定
is_close_zero = math.isclose(near_zero_a, near_zero_b, abs_tol=0.0001)
print(f"0付近の比較: {is_close_zero}")
実行結果:
0付近の比較: True
まとめ
- 浮動小数点数(float)の比較に
==を使うと、計算誤差により意図しない結果になる場合があります。 math.isclose(a, b)を使用することで、誤差を考慮した正しい比較が可能になります。- 必要に応じて
rel_tol(相対誤差)やabs_tol(絶対誤差)を指定し、許容範囲を調整します。
数値計算を伴うプログラムでは、バグを防ぐために math.isclose() の使用が推奨されます。
