web-dev-qa-db-ja.com

浮動小数点出力の単体テストを実行するにはどうすればよいですか? -python

浮動小数点数を返す関数の単体テストを書いているとしましょう。私のマシンのように、完全な精度でそれを行うことができます。

_>>> import unittest
>>> def div(x,y): return x/float(y)
... 
>>>
>>> class Testdiv(unittest.TestCase):
...     def testdiv(self):
...             assert div(1,9) == 0.1111111111111111
... 
>>> unittest.main()
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
_

同じ完全浮動小数点精度は、OS /ディストリビューション/マシン全体で同じですか?

以下のように丸めて、単体テストを試すことができます:

_>>> class Testdiv(unittest.TestCase):
...     def testdiv(self):
...             assert round(div(1,9),4) == 0.1111
... 
>>>
_

また、log(output)を使用してアサートを実行することもできますが、小数点以下の精度を維持するには、丸めまたは切り捨てを行う必要があります。

しかし、浮動小数点出力のユニットテストをPythonで処理する他の方法は何ですか?

18
alvas

Python=のfloatの精度は、基になるCの表現に依存します。From Tutorial/Floating Point Arithmetic:Issues and Limitations、15.1

今日のほとんどすべてのマシン(2000年11月)はIEEE-754浮動小数点演算を使用しており、ほとんどすべてのプラットフォームがPython floatsをIEEE-754「倍精度」にマップします。


テストに関しては、既存の機能を使用することをお勧めします。 TestCase.assertAmostEqual

assertAlmostEqual(first、second、Places = 7、msg = None、delta = None)

first second がほぼ等しい(またはほぼ等しくない)であることをテストするために、差を計算し、指定された小数に丸めます places (デフォルトは7)、ゼロと比較します。 places の代わりに delta が指定されている場合、 first second は、 delta 以下でなければなりません。

例:

import unittest

def div(x, y): return x / float(y)

class Testdiv(unittest.TestCase):
    def testdiv(self):
        self.assertAlmostEqual(div(1, 9), 0.1111111111111111)
        self.assertAlmostEqual(div(1, 9), 0.1111, places=4)

unittest.main() # OK

assertステートメントを使いたい場合は、 math.isclose (Python 3.5+)を使用できます。

import unittest, math

def div(x, y): return x / float(y)

class Testdiv(unittest.TestCase):
    def testdiv(self):
        assert math.isclose(div(1, 9), 0.1111111111111111)

unittest.main() # OK

math.closeのデフォルトの相対許容誤差は1e-09、 "です。これにより、2つの値が約9桁の10進数内で同じになります。" math.closeの詳細については、 PEP 485 を参照してください。

29
vaultah

unittest.TestCaseクラスには、フロートを比較するための特定のメソッドがあります: assertAlmostEqual および assertNotAlmostEqual 。ドキュメントを引用するには:

assertAlmostEqualfirst、second、Places = 7、msg = None、delta = NoneassertNotAlmostEqualfirst、second、Places = 7、msg = None、delta = None

firstsecondが、差を計算し、与えられた値に丸めることにより、ほぼ等しい(またはほぼ等しくない)ことをテスト10進数の数places(デフォルトは7)、ゼロとの比較。これらのメソッドは、値を所定の数のdecimal placesに丸めます(つまり、 round() 関数のように)。有効数字

placesの代わりにdeltaが指定されている場合、first /の違いおよびsecondは、delta以下でなければなりません。

したがって、次のように関数をテストできます。

self.assertAlmostEqual(div(1, 9), 0.1111111111111111)  # round(a-b, 7) == 0
self.assertAlmostEqual(div(1, 9), 0.1111, 4)           # round(a-b, 4) == 0

余談ですが、テストランナーとしてpytestを使用しない限り、メソッドによって生成されるテスト失敗メッセージは一般的にはるかに有益であるため、TestCase.assert*メソッドをassertステートメントよりも優先する必要があります。

9
Eugene Yarmash