用Numpy减轻浮点逼近问题

时间:2019-07-01 15:34:00

标签: python numpy floating-point floating-accuracy

我的代码很简单,只有1行引起了问题:

np.tan(np.radians(rotation))

我得到的rotation = 45的预期输出不是1,而是0.9999999999999999。我知道0和9等于1是一吨,但是,在我的用例中,似乎肯定会在迭代中建立起来的东西。

是什么导致浮点错误:np.tannp.radians,以及如何在不考虑浮点错误的情况下正确显示问题函数?

编辑:

我应该澄清一下,我对浮点错误很熟悉。我担心的是,随着该数字的增加,增加和比较,1e-6错误突然变成一个明显的问题。我通常可以安全地忽略浮点问题,但是现在我更加担心错误的累积。我想减少发生此类错误的可能性。

编辑2:

我当前的解决方案是将四舍五入到小数点后8位,因为这很有可能。这是一个临时解决方案,因为我更喜欢一种绕过IEEE十进制表示形式的方法。

2 个答案:

答案 0 :(得分:1)

  

是什么导致浮点错误:np.tannp.radians,以及如何在不考虑浮点错误的情况下正确显示问题函数?

这两个函数均会产生舍入错误,因为在任何情况下都不能以浮点表示精确的结果。

  

我当前的解决方案是将四舍五入到小数点后8位,因为这很有可能。这是一个临时解决方案,因为我更喜欢一种绕过IEEE十进制表示形式的方法。

该问题与十进制表示形式无关,这将在您上面提到的确切情况之外给出更差的结果,例如

>>> np.tan(np.radians(60))
1.7320508075688767
>>> round(np.tan(np.radians(60)), 8)
1.73205081
>>> np.sqrt(3) # sqrt is correctly rounded, so this is the closest float to the true result
1.7320508075688772

如果您绝对需要比上面代码中的15位小数位数更高的精度,则可以使用gmpy2之类的任意精度库。

答案 1 :(得分:0)

在这里看看:https://docs.scipy.org/doc/numpy/user/basics.types.html

numpy中的标准dtype不会超过64位精度。从文档中:

  

请注意,即使np.longdouble比python提供更高的精度   浮点数,很容易失去额外的精度,因为python通常   强制值通过浮点型。例如,%格式   运算符要求将其参数转换为标准python   类型,因此无法保持扩展的精度   即使要求许多小数位。测试可能有用   您的代码的值为1 + np.finfo(np.longdouble).eps

您可以使用np.longdouble来提高精度,但这取决于平台

在spyder中(Windows):

np.finfo(np.longdouble).eps  #same precision as float
>> 2.220446049250313e-16
np.finfo(np.longdouble).precision
>> 15

在Google colab中:

np.finfo(np.longdouble).eps  #larger precision
>> 1.084202172485504434e-19
np.finfo(np.longdouble).precision
>> 18

print(np.tan(np.radians(45, dtype=np.float), dtype=np.float) - 1)
print(np.tan(np.radians(45, dtype=np.longfloat), dtype=np.longfloat) - 1)
>> -1.1102230246251565e-16
0.0