3

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

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

印刷:

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

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

我不知道它是否有任何关系,但谷歌计算器也无法处理这个计算。这是谷歌计算器的输出:

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

是什么导致了这个计算错误?以及如何在我的 Python 程序中避免它?

4

2 回答 2

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

于 2011-05-13T20:30:08.240 回答
2

str和之间的区别repr

>>> 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(谷歌给你的)。或者,如果你做了 round(3.14159,5) + round(3.14159,5) % (3.14159 + 3.14159) = 6.2832 % 6.28318 = 2e-5。

因此,通过四舍五入到 N 位(通过使用strwhich 有效地四舍五入数字),您的计算只能精确到小于 N 位。为了使这项工作继续进行,强制四舍五入到某个更高的数字(为安全起见,保留两位计算的数字)是必要的。例如,str 在数字 12 处四舍五入,所以也许我们应该在数字 10 处四舍五入。

>>> round(6.28187631024 + 0.001308996939,10) % (round(pi * 2,10))
0
于 2011-05-13T20:31:29.060 回答