Python で浮動小数点数の比較を扱う方法

PythonPythonBeginner
オンラインで実践に進む

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

浮動小数点数は、Python で数値計算に広く使用されていますが、値を比較する際に、その表現方法が予期しない動作を引き起こすことがあります。このチュートリアルでは、Python での浮動小数点数の表現の基本を解説し、正確な浮動小数点数の比較を行うための実用的な手法を紹介します。

Python での浮動小数点数の表現

Python では、浮動小数点数は IEEE 754 規格を使用して表現されます。これは、コンピュータで実数を表現するために広く採用されている規格です。この規格では、正の無限大や負の無限大、非数 (NaN) などの特殊な値の表現を含む、浮動小数点数演算の形式と動作が定義されています。

浮動小数点数の表現

Python の浮動小数点数は、64 ビット形式(「倍精度」浮動小数点数とも呼ばれます)で格納されます。この形式は、3 つの要素で構成されています。

  1. 符号ビット:数値が正か負かを決定します。
  2. 指数部:仮数部を 2 の何乗にするかを表します。
  3. 仮数部:数値の小数部分です。

Python での浮動小数点数の表現は、次のように視覚化できます。

graph TD A[Sign Bit] --> B[Exponent] B --> C[Significand]

IEEE 754 規格では、正のゼロや負のゼロ、正の無限大や負の無限大、NaN などの特殊な値を表すための特定のビットパターンが定義されています。

精度と丸め

コンピュータでの浮動小数点数演算は、数値を表現するために使用されるビット数が有限であるため、必ずしも正確ではありません。これにより、丸め誤差や浮動小数点数の比較時の予期しない動作が発生することがあります。たとえば、次のコードはその問題を示しています。

import sys

x = 0.1
y = 0.2
print(x + y)  ## Output: 0.30000000000000004

このような動作が起こる理由は、0.1 と 0.2 の二進数表現を、浮動小数点数を格納するために使用される有限のビット数で正確に表現できないからです。

この問題を解決するために、次のセクションでは正確な浮動小数点数の比較手法について説明します。

浮動小数点数の比較

Python で浮動小数点数を比較することは、その表現に内在する不正確さのために難しい場合があります。以下の手法を使って、正確な浮動小数点数の比較を行うことができます。

絶対誤差比較

最も単純なアプローチは、2 つの浮動小数点数の絶対誤差が小さな閾値よりも小さいかどうかをチェックすることです。この方法は、比較する値の予想される精度がわかっている場合に適しています。

import sys

x = 0.1
y = 0.2
epsilon = sys.float_info.epsilon  ## 1.0 + x!= 1.0 となる最小の正の浮動小数点数 x
if abs(x + y - 0.3) < epsilon:
    print("x + y is equal to 0.3")
else:
    print("x + y is not equal to 0.3")

相対誤差比較

比較する数値の大きさが異なる場合、相対誤差比較がより適切な場合があります。この方法では、数値間の絶対誤差が数値の大きさに比べて小さいかどうかをチェックします。

import sys

x = 1.0
y = 1.000000001
epsilon = sys.float_info.epsilon
if abs(x - y) / max(abs(x), abs(y)) < epsilon:
    print("x is equal to y")
else:
    print("x is not equal to y")

ULP (Unit in the Last Place) 比較

ULP 比較法では、2 つの浮動小数点数の差が、最下位ビットのある一定の単位 (ULP) よりも小さいかどうかをチェックします。このアプローチは、絶対誤差や相対誤差比較法よりも正確です。

import math

x = 0.1
y = 0.100000000000001
if abs(x - y) <= 2 * math.ulp(max(x, y)):
    print("x is equal to y")
else:
    print("x is not equal to y")

これらの手法を使うことで、Python で浮動小数点数を効果的に比較し、その表現に内在する不正確さを処理することができます。

正確な浮動小数点数比較の手法

Python で浮動小数点数を扱う際には、正確な比較を行うために適切な手法を使うことが重要です。以下にいくつかの手法を紹介します。

絶対誤差比較

絶対誤差比較では、2 つの浮動小数点数の絶対誤差が小さな閾値よりも小さいかどうかをチェックします。この方法は、比較する値の予想される精度がわかっている場合に適しています。

import sys

x = 0.1
y = 0.2
epsilon = sys.float_info.epsilon  ## 1.0 + x!= 1.0 となる最小の正の浮動小数点数 x
if abs(x + y - 0.3) < epsilon:
    print("x + y is equal to 0.3")
else:
    print("x + y is not equal to 0.3")

相対誤差比較

相対誤差比較では、2 つの浮動小数点数の絶対誤差が数値の大きさに比べて小さいかどうかをチェックします。この方法は、比較する数値の大きさが異なる場合に役立ちます。

import sys

x = 1.0
y = 1.000000001
epsilon = sys.float_info.epsilon
if abs(x - y) / max(abs(x), abs(y)) < epsilon:
    print("x is equal to y")
else:
    print("x is not equal to y")

ULP (Unit in the Last Place) 比較

ULP 比較法では、2 つの浮動小数点数の差が、最下位ビットのある一定の単位 (ULP) よりも小さいかどうかをチェックします。このアプローチは、絶対誤差や相対誤差比較法よりも正確です。

import math

x = 0.1
y = 0.100000000000001
if abs(x - y) <= 2 * math.ulp(max(x, y)):
    print("x is equal to y")
else:
    print("x is not equal to y")

これらの手法を使うことで、Python で浮動小数点数の比較を効果的に行い、計算において望ましい精度を確保することができます。

まとめ

この Python チュートリアルでは、浮動小数点数の表現に関する課題と、正確な浮動小数点数の比較を行うための効果的な戦略について学びました。基本的な原理を理解し、ここで説明した手法を適用することで、浮動小数点数の演算と比較を正確に処理する、より堅牢で信頼性の高い Python コードを書くことができます。