Python float32/float64 numpy变量的不同行为
谷歌搜索了一段时间后,我在这里发帖寻求帮助 我有两个从函数返回的float64变量。 他们两人显然都是1:Python float32/float64 numpy变量的不同行为,python,numpy,Python,Numpy,谷歌搜索了一段时间后,我在这里发帖寻求帮助 我有两个从函数返回的float64变量。 他们两人显然都是1: >>> x, y = somefunc() >>> print x,y >>> if x < 1 : print "x < 1" >>> if y < 1 : print "y < 1" 1.0 1.0 y < 1 希望看到变量之间的差异,但即使如此,它们在打印时都显示为1.0
>>> x, y = somefunc()
>>> print x,y
>>> if x < 1 : print "x < 1"
>>> if y < 1 : print "y < 1"
1.0 1.0
y < 1
希望看到变量之间的差异,但即使如此,它们在打印时都显示为1.0
在这一点上我有点困惑。
有没有办法把这些数字的差别形象化?
是否可以可靠地使用“if/then”检查浮点数
谢谢
特雷瓦雷斯
In [26]: x = numpy.float64("1.000000000000001")
In [27]: print x, repr(x)
1.0 1.0000000000000011
换句话说,在print
语句中,您会受到精度损失的困扰。该值与1
略有不同。打印的值不正确。在您的情况下,使用float64
时y
小于1
,使用float32
时大于或等于1
。这是意料之中的,因为舍入误差取决于浮点的大小
为避免此类问题,在处理浮点数时,应始终确定一个“最小误差”,通常称为epsilon
,并检查结果是否与目标值最远epsilon
,而不是进行相等性比较:
In [13]: epsilon = 1e-11
In [14]: number = np.float64(1) - 1e-16
In [15]: target = 1
In [16]: abs(number - target) < epsilon # instead of number == target
Out[16]: True
还请注意,在交互式解释器中执行print y
或计算y
会得到不同的结果:
In [1]: import numpy as np
In [2]: np.float(1) - 1e-16
Out[2]: 0.9999999999999999
In [3]: print(np.float64(1) - 1e-16)
1.0
不同之处在于,在评估调用时,print
调用str
:
In [9]: str(np.float64(1) - 1e-16)
Out[9]: '1.0'
In [10]: repr(np.float64(1) - 1e-16)
Out[10]: '0.99999999999999989'
根据这里提供的建议,我以这种方式总结了答案:
为了在浮点数之间进行比较,程序员必须定义一个最小距离(eps),以便将它们视为不同的(例如,eps=1e-12)。这样做时,条件应如下所示:
Instead of (x>a), use (x-a)>eps
Instead of (x<a), use (a-x)>eps
Instead of (x==a), use abs(x-a)<eps
使用(x-a)>eps代替(x>a)
而不是(xeps
使用abs(x-a)代替(x==a)我不理解你的问题。显然错误在打印的表示法中,y
在float64
情况下小于1,并且相等(或更大)由于舍入错误,在使用float32
时设置为1
。在处理浮点值时,您永远不能使用相等的比较。修复最小错误(例如epsilon=1e-16
或更小/更大,取决于应用程序),如果abs(数字-1),则执行
@Bakuriu您可以将此作为一个答案发布…您已经解释了正在发生的事情,print
输出11个有效数字,float64有15个左右。谢谢您Bakuriu,这是一个非常全面的答案,澄清了我的疑问。我只是想知道是什么Numpy提供函数作为“Numpy.where”的要点,没有关于浮点数的这些细微之处的警告?从文档中可以看出,它可以直接用于浮点数,而不考虑精度问题:>>>x=np.arange(9.)。重塑(3,3)>>x[np.where(x>3.0)]数组([4,5,6,7,8])@Trevarez这不是numpy的问题。这是任何浮点计算的问题。这是你应该知道的(参见示例)。如果你想检查哪些值大于3.0
,达到一定精度,你可以先减去ε(即x[np.where((x-epsilon)>3.0)]
)。很棒的文章。我想我终于理解了“问题”的范围。再次感谢您的解释。注意:您应该使用np.allclose(value,other_value)
。不要定义您自己的任意ε值。
In [9]: str(np.float64(1) - 1e-16)
Out[9]: '1.0'
In [10]: repr(np.float64(1) - 1e-16)
Out[10]: '0.99999999999999989'
Instead of (x>a), use (x-a)>eps
Instead of (x<a), use (a-x)>eps
Instead of (x==a), use abs(x-a)<eps