Pythonで浮動小数点数を比較する:math.isclose()の使い方と誤差への対処

コンピュータで小数を扱う場合、内部的には2進数で表現されるため、どうしても微細な「計算誤差」が発生します。そのため、浮動小数点数(float)同士を == 演算子で比較すると、人間が期待する結果にならないことがあります。

Python 3.5以降では、この問題を解決するために標準ライブラリ math モジュールに isclose() 関数が追加されました。

この記事では、浮動小数点数の比較で発生する問題点と、math.isclose() を使った正しい比較方法について解説します。

目次

浮動小数点数の比較における問題点

まずは、単純な足し算の結果を比較してみます。0.1 + 0.20.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() の使用が推奨されます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次