简体   繁体   English

如何对浮点输出执行单元测试? - Python

[英]How to perform unittest for floating point outputs? - python

Let's say I am writing a unit test for a function that returns a floating point number, I can do it as such in full precision as per my machine:假设我正在为一个返回浮点数的函数编写单元测试,我可以按照我的机器以全精度完成它:

>>> 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

Will the same full floating point precision be the same across OS/distro/machine?跨操作系统/发行版/机器的相同全浮点精度是否相同?

I could try to round off and do a unit test as such:我可以尝试四舍五入并进行单元测试:

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

I could also do an assert with log(output) but to keep to a fix decimal precision, I would still need to do rounding or truncating.我也可以用log(output)做一个断言,但为了保持固定的十进制精度,我仍然需要做四舍五入或截断。

But what other way should one pythonically deal with unittesting for floating point output?但是,python 上应该用什么其他方式来处理浮点输出的单元测试?

The precision of float in Python is dependent on the underlying C representation. Python 中float的精度取决于底层的 C 表示。 From Tutorial/Floating Point Arithmetic: Issues and Limitations, 15.1 :来自教程/浮点运算:问题和限制,15.1

Almost all machines today (November 2000) use IEEE-754 floating point arithmetic, and almost all platforms map Python floats to IEEE-754 “double precision”.今天(2000 年 11 月)几乎所有机器都使用 IEEE-754 浮点运算,几乎所有平台都将 Python 浮点数映射到 IEEE-754 “双精度”。


As for testing, a better idea is to use existing functionality, eg TestCase.assertAlmostEqual :至于测试,更好的主意是使用现有功能,例如TestCase.assertAlmostEqual

assertAlmostEqual(first, second, places=7, msg=None, delta=None) assertAlmostEqual(第一,第二,地方= 7,味精=无,增量=无)

Test that first and second are approximately (or not approximately) equal by computing the difference, rounding to the given number of decimal places (default 7), and comparing to zero.测试的第一第二大致的(或不近似)通过计算差,舍入到给定的数小数(默认7),以及比较等于零。 If delta is supplied instead of places then the difference between first and second must be less or equal to (or greater than) delta .如果提供delta而不是地方,firstsecond之间的差异必须小于或等于(或大于) delta

Example:例子:

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

If you prefer to stick to assert statement, you could use the math.isclose (Python 3.5+):如果您更喜欢坚持使用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

The default relative tolerance of math.close is 1e-09, "which assures that the two values are the same within about 9 decimal digits." math.close的默认相对容差是 1e-09, “这确保两个值在大约 9 个十进制数字内相同。” . . For more information about math.close see PEP 485 .有关math.close更多信息,请参阅PEP 485

The unittest.TestCase class has specific methods for comparing floats: assertAlmostEqual and assertNotAlmostEqual . unittest.TestCase类具有用于比较浮点数的特定方法: assertAlmostEqualassertNotAlmostEqual To quote the documentation:引用文档:

assertAlmostEqual ( first, second, places=7, msg=None, delta=None ) assertNotAlmostEqual ( first, second, places=7, msg=None, delta=None ) assertAlmostEqual ( first, second, place=7, msg=None, delta=None ) assertNotAlmostEqual ( first, second, place=7, msg=None, delta=None )

Test that first and second are approximately (or not approximately) equal by computing the difference, rounding to the given number of decimal places (default 7), and comparing to zero.测试的第一第二大致的(或不近似)通过计算差,舍入到给定的数小数(默认7),以及比较等于零。 Note that these methods round the values to the given number of decimal places (ie like the round() function) and not significant digits .请注意,这些方法将值四舍五入到给定的小数位数(即如round()函数)而不是有效数字

If delta is supplied instead of places then the difference between first and second must be less or equal to (or greater than) delta .如果提供delta而不是地方,firstsecond之间的差异必须小于或等于(或大于) delta

Thus, you could test the function like this:因此,您可以像这样测试函数:

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

On a side note, unless you use pytest as a tests runner, you should prefer the TestCase.assert* methods to bare assert statements, as the test failure messages produced by the methods are generally much more informative.附带说明一下,除非您使用pytest作为测试运行器,否则您应该更喜欢TestCase.assert*方法而不是裸assert语句,因为这些方法产生的测试失败消息通常提供更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM