我被要求测试第三方提供的图书馆.众所周知,该库对于n个有效数字是准确的.可以安全地忽略任何不太重要的错误.我想写一个函数来帮助我比较结果:
def nearlyequal( a, b, sigfig=5 ):
此函数的目的是确定两个浮点数(a和b)是否大致相等.如果a == b(完全匹配),或者当以十进制写入舍入为sigfig有效数字时a和b具有相同的值,则该函数将返回True .
任何人都可以建议一个好的实施?我写了一个迷你单元测试.除非你能在我的测试中看到一个错误,否则一个好的实现应该传递以下内容:
assert nearlyequal(1, 1, 5) assert nearlyequal(1.0, 1.0, 5) assert nearlyequal(1.0, 1.0, 5) assert nearlyequal(-1e-9, 1e-9, 5) assert nearlyequal(1e9, 1e9 + 1 , 5) assert not nearlyequal( 1e4, 1e4 + 1, 5) assert nearlyequal( 0.0, 1e-15, 5 ) assert not nearlyequal( 0.0, 1e-4, 6 )
补充说明:
值a和b可以是int,float或numpy.float64类型.值a和b将始终为相同类型.转换不会在函数中引入额外的错误,这一点至关重要.
让我们保持这个数字,所以转换为字符串或使用非数学技巧的函数并不理想.该程序将由一位数学家进行审核,他希望能够证明该功能能够完成它应该做的事情.
速度......我必须比较很多数字,所以越快越好.
我有numpy,scipy和标准库.对我来说,任何其他事情都很难获得,特别是对于项目的这么小的一部分.
erb.. 65
从Python 3.5开始,使用该函数的标准方法(使用标准库)math.isclose
.
它有以下签名:
isclose(a, b, rel_tol=1e-9, abs_tol=0.0)
具有绝对容错的用法示例:
from math import isclose a = 1.0 b = 1.00000001 assert isclose(a, b, abs_tol=1e-8)
如果您希望它具有n位有效数字的精度,只需将最后一行替换为:
assert isclose(a, b, abs_tol=10**-n)
dF... 21
有一个函数assert_approx_equal
中numpy.testing
(源在这里)这可能是一个很好的起点.
def assert_approx_equal(actual,desired,significant=7,err_msg='',verbose=True): """ Raise an assertion if two items are not equal up to significant digits. .. note:: It is recommended to use one of `assert_allclose`, `assert_array_almost_equal_nulp` or `assert_array_max_ulp` instead of this function for more consistent floating point comparisons. Given two numbers, check that they are approximately equal. Approximately equal is defined as the number of significant digits that agree.
Triptych.. 8
这是一个需要.
def nearly_equal(a,b,sig_fig=5): return ( a==b or int(a*10**sig_fig) == int(b*10**sig_fig) )
Oren Shemesh.. 5
我相信您对问题的定义不够好,您提出的单元测试证明了这一点:
如果“四舍五入到N个sig-fig小数位”是指“小数点右边的N个小数位”,那么该测试assert nearlyequal(1e9, 1e9 + 1 , 5)
应该会失败,因为即使将1000000000和1000000001的精度四舍五入为0.00001,它们仍然是不同的。
如果“四舍五入到N个sig-fig小数点后assert nearlyequal(-1e-9, 1e-9, 5)
一位”是指“ N个最高有效数字,而不管小数点是多少”,则测试应该失败,因为以这种方式查看时0.000000001和-0.000000001完全不同。
如果您的意思是第一个定义,那么此页面上的第一个答案(由Triptych设计)是不错的。如果您的意思是第二个定义,请说出来,我保证会考虑一下:-)
从Python 3.5开始,使用该函数的标准方法(使用标准库)math.isclose
.
它有以下签名:
isclose(a, b, rel_tol=1e-9, abs_tol=0.0)
具有绝对容错的用法示例:
from math import isclose a = 1.0 b = 1.00000001 assert isclose(a, b, abs_tol=1e-8)
如果您希望它具有n位有效数字的精度,只需将最后一行替换为:
assert isclose(a, b, abs_tol=10**-n)
有一个函数assert_approx_equal
中numpy.testing
(源在这里)这可能是一个很好的起点.
def assert_approx_equal(actual,desired,significant=7,err_msg='',verbose=True): """ Raise an assertion if two items are not equal up to significant digits. .. note:: It is recommended to use one of `assert_allclose`, `assert_array_almost_equal_nulp` or `assert_array_max_ulp` instead of this function for more consistent floating point comparisons. Given two numbers, check that they are approximately equal. Approximately equal is defined as the number of significant digits that agree.
这是一个需要.
def nearly_equal(a,b,sig_fig=5): return ( a==b or int(a*10**sig_fig) == int(b*10**sig_fig) )
我相信您对问题的定义不够好,您提出的单元测试证明了这一点:
如果“四舍五入到N个sig-fig小数位”是指“小数点右边的N个小数位”,那么该测试assert nearlyequal(1e9, 1e9 + 1 , 5)
应该会失败,因为即使将1000000000和1000000001的精度四舍五入为0.00001,它们仍然是不同的。
如果“四舍五入到N个sig-fig小数点后assert nearlyequal(-1e-9, 1e-9, 5)
一位”是指“ N个最高有效数字,而不管小数点是多少”,则测试应该失败,因为以这种方式查看时0.000000001和-0.000000001完全不同。
如果您的意思是第一个定义,那么此页面上的第一个答案(由Triptych设计)是不错的。如果您的意思是第二个定义,请说出来,我保证会考虑一下:-)