浮点模数问题

时间:2011-05-13 20:24:25

标签: python floating-point modulus

我在Python中的浮点数上遇到模数问题。这段代码:

...
print '(' + repr(olddir) + ' + ' + repr(self.colsize) + ') % (math.pi*2) = ' + repr((olddir+self.colsize)
...

打印:

(6.281876310240881 + 0.001308996938995747) % (math.pi*2) = 2.9043434324194095e-13

我知道浮点数不准确。但我无法理解这一点。

我不知道它是否有任何相关性,但Google Calculator也无法处理此计算。这是Google Calculator的输出:

(6.28187631024 + 0.001308996939) % (pi * 2) = 6.28318531

导致此计算错误的原因是什么?我怎样才能在Python程序中避免它?

2 个答案:

答案 0 :(得分:4)

使用str()打印浮点数实际上会打印数字的圆形版本:

>>> print repr(math.pi)
3.1415926535897931
>>> print str(math.pi)
3.14159265359

因此我们无法真正重现您的结果,因为我们不知道您正在进行计算的确切值。显然,olddir+self.colsize的确切值略大于2*math.pi,而您在Google Calculator中使用的舍入值之和略小于2*math.pi

答案 1 :(得分:2)

strrepr

之间的差异
>>> import scipy
>>> pi = scipy.pi
>>> str(pi)
'3.14159265359'
>>> repr(pi)
'3.1415926535897931'

str将浮点数截断为12位数,其中repr给出内部表示(作为字符串)。

编辑:总而言之,问题出现了,因为你过早地进行了舍入,并通过非常接近它的数字来计算某事物的模数。对于浮点数,舍入不可避免地涉及将十进制数转换为二进制数。

首先,举例说明舍入如何通过实际数学(不是浮点数学)来伤害你。看(3.14 + 3.14)%(3.14 + 3.14),显然为零。现在,如果我们首先将数字四舍五入到一个十进制数字会发生什么?好(3.1 + 3.1)%(3.14 + 3.14)= 6.2%(6.28)= 6.2(谷歌给你的)。或者,如果你做了回合(3.14159,5)+回合(3.14159,5)%(3.14159 + 3.14159)= 6.2832%6.28318 = 2e-5。

因此,通过舍入到N位数(通过使用有效舍入数字的str),您的计算仅精确到小于N位数。要使这项工作继续进行,必须以更高的数字进行四舍五入(保持两个计算的数字以确保安全)。例如,str在第12位进行,所以也许我们应该在第10位进行舍入。

>>> round(6.28187631024 + 0.001308996939,10) % (round(pi * 2,10))
0