浮点模数问题
我在 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 计算器的输出:
(6.28187631024 + 0.001308996939) % (pi * 2) = 6.28318531
是什么导致了此计算错误?我怎样才能在我的Python程序中避免这种情况呢?
I'm having a problem with modulus on a floating point number in Python. This code:
...
print '(' + repr(olddir) + ' + ' + repr(self.colsize) + ') % (math.pi*2) = ' + repr((olddir+self.colsize)
...
Prints:
(6.281876310240881 + 0.001308996938995747) % (math.pi*2) = 2.9043434324194095e-13
I know floating point numbers aren't precise. But I can't get this to make any sense.
I don't know if it is in any way related but Google Calculator can't handle this calculation either. This is the output from Google Calculator:
(6.28187631024 + 0.001308996939) % (pi * 2) = 6.28318531
What is causing this calculation error? And how can I avoid it in my Python program?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用
str()
打印浮点数实际上会打印该数字的舍入版本:因此我们无法真正重现您的结果,因为我们不知道您正在计算的确切值和。显然,
olddir+self.colsize
的精确值略大于2*math.pi
,而您在 Google 计算器中使用的舍入值的总和略小比2*math.pi
。Using
str()
to print a floating point number actually prints a rounded version of the number:So we can't really reproduce your results, since we don't know the exact values you are doing the computation with. Obviously, the exact value of
olddir+self.colsize
is slightly greater than2*math.pi
, while the sum of the rounded values you used in Google Calculator is slightly less than2*math.pi
.str
和repr
之间的区别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 位(通过使用
str
有效地对数字进行四舍五入),您的计算只能精确到少于 N 位。为了使这项工作继续进行,有必要强制舍入到更高的数字(为了安全起见,保留两个计算的数字)。例如,str 在数字 12 处四舍五入,所以也许我们应该在数字 10 处四舍五入。The difference between
str
andrepr
str
truncates floating point numbers to 12 digits, where repr gives the internal representation (as a string).EDIT: So in summary, the problem arose because you rounded prematurely and are calculating the modulus of something via a number that's very close to it. With floating point numbers, rounding is inevitably involved in converting decimal numbers into binary.
First, do an example of how rounding hurts you with actual math (not floating point math). Look at (3.14+3.14) % (3.14+3.14), which is obviously zero. Now what would happen if we rounded the digits to one decimal digit first on one side? Well (3.1+3.1) % (3.14+3.14) = 6.2 % (6.28) = 6.2 (what google gave you). Or if you did round(3.14159,5) + round(3.14159,5) % (3.14159 + 3.14159) = 6.2832 % 6.28318 = 2e-5.
So in by rounding to N digits (by using
str
which effectively rounds the numbers), your calculation is only accurate to less than N digits. To have this work going forward force rounding at some higher digit (keeping two calculated digits for safety) is necessary. E.g., str rounds at digit 12, so maybe we should round at digit 10.