web-dev-qa-db-ja.com

浮動小数点の等価性のテスト

Pythonで浮動小数点近似式をテストする関数はありますか?何かのようなもの、

 def approx_equal(a, b, tol):
     return abs(a - b) < tol

私の使用例は、GoogleのC++テストライブラリgtest.hがEXPECT_NEARを定義する方法に似ています。

次に例を示します。

def bernoulli_fraction_to_angle(fraction):
    return math.asin(sqrt(fraction))
def bernoulli_angle_to_fraction(angle):
    return math.sin(angle) ** 2
def test_bernoulli_conversions():
    assert(approx_equal(bernoulli_angle_to_fraction(pi / 4), 0.5, 1e-4))
    assert(approx_equal(
              bernoulli_fraction_to_angle(bernoulli_angle_to_fraction(0.1)),
                0.1, 1e-4))
36
Neil G
  • 数値を比較するために、math.iscloseとして PEP 485 以降Python 3.5。
  • 数値または配列を比較するために、numpy.allclose
  • 数値または配列をテストする場合、numpy.testing.assert_allclose
51
Neil G

別のアプローチは、2つの数値の 相対変化 (または相対差)を計算することです。これは、「比較されるものの「サイズ」を考慮しながら2つの量を比較するために使用されます」。 Wikipediaの記事で言及されている2つの formulas は、Pythonで次のような比較に使用できます。これは、比較される値の一方または両方がゼロの場合も処理します。

def approx_equal(a, b, tol):
    return abs(a-b) <= max(abs(a), abs(b)) * tol

def approx_equal(a, b, tol):
    return abs(a-b) <= (abs(a)+abs(b))/2 * tol

どちらの場合も、計算値は単位のない分数です。前者の場合、ベースライン値は2つの数値の最大絶対値であり、後者の場合は、それらの平均絶対値です。この記事では、それぞれの長所と短所について詳しく説明します。後者は、比較の前に100を掛けると パーセントの差 になる可能性があります(tolがパーセントの値になります)。この記事では、変化する値が「パーセンテージ自体である場合は、パーセンテージポイントを使用してその変化について説明することをお勧めします」、つまり絶対的な変化を示唆しています。

これらの方法は両方とも(明らかに)、2つの数値の差の絶対値を単に取るよりも少し多くの計算を必要とします。

19
martineau

Pythonで浮動小数点近似式をテストする関数はありますか?

定義はコンテキストに依存するため、a関数は使用できません。

def eq( a, b, eps=0.0001 ):
    return abs(a - b) <= eps

常に機能するとは限りません。ある状況があります

def eq( a, b, eps=0.0001 ):
     return abs( a - b ) / abs(a) <= eps

より適切かもしれません。

さらに、常に人気があります。

def eq( a, b, eps=0.0001 ):
    return abs(math.log( a ) - math.log(b)) <=  eps

どちらがより適切かもしれません。

a(単一)関数がすべての数学的な選択肢を組み合わせる方法を求める方法がわかりません。用途によりますので。

8
S.Lott

私があなただったら、私はあなたが書いたものを使用し、それを別のモジュールに入れます(おそらく他のユーティリティではPythonは実装がない)か、または必要なコードのトップ。

ラムダ式を使用することもできます(私のお気に入りの言語機能の1つですが、おそらくあまり明確ではありません)。

approx_equal = lambda a, b, t: abs(a - b) < t
5
Rafe Kettler

等しいかどうかの浮動小数点数を比較することは、通常は悪い考えです。使用している公差機能を使用しても、これは実際に実行したいことではありません。

浮動小数点数を使用する場合、妥当なオプションは、不等式を使用するようにアルゴリズムをリファクタリングすることです。a < bこれは、期待どおりの結果をもたらす可能性が高く、偽陰性または陽性がはるかに少なく、最も重要なのは、それらが等しくなるためにそれらが等しくなければならないことを推測する必要はありません。

それができない場合は、正確な表現を使用することもできます。アルゴリズムが算術演算(+-*および/)のみで構成されている場合は、fractions.Fractionで提供されるように、有理表現を使用できます。 、またはdecimal.Decimalは、必要なものです(たとえば、財務計算で)。

アルゴリズムを任意の精度表現で簡単に表現できない場合、別の選択肢は、たとえば this module を使用して、区間演算で丸め誤差を明示的に管理することです。

チュートリアル によると:

...数値を意図した正確な値に近づけることはできませんが、round()関数は後丸めに役立ち、不正確な値の結果が互いに比較できるようになります...

したがって、これがPythonで「isclose」関数を定義する方法です。

def isclose(a, b, ndigits):
   return round(a-b, ndigits) == 0

私は通常、ndigitsとして5を使用します。ただし、期待する精度によって異なります。

0
Saeid BK