2013-10-21 46 views
-3

我尝试在Python这个简单的数学运算Python的数学精度

>>> math.floor(8.2-0.21) 
7.0 
>>> math.floor(8.21-0.2) 
8.0 
>>> math.floor(8.2-0.2) 
7.0 

第三个应该返回8,但它是返回7?

UPDATE

我已经尝试在PHP,Ruby和JAVA,我已经得到了相同的结果。

更新2 我不知道为什么这个问题得到很多票下来!

+0

你的数学错了我认为......也许你想'math.round'? –

+2

你在每个人都回答你之后编辑它,但你的第三个例子是浮点错误。 – roippi

+0

我的意思是8.2 - 0.2,我已更新问题 – shox

回答

6

的语言您引用IEEE-754 64位二进制浮点或使用底层硬件的浮点,这可能是IEEE-754二进制浮点。

在IEEE-754 64位二进制浮点数中,8.2的最接近的可表示值是8.199999999999999289457264239899814128875732421875,最接近的可表示值为0.2。200000000000000011102230246251565404236316680908203125.

所以,当你写8.2 - 0.2,实际发生的事情是,0.200000000000000011102230246251565404236316680908203125从8.199999999999999289457264239899814128875732421875扣除。结果是略低于8的值,并且稍低于8的值的底面是7.

这里的教训是浮点算法通常是近似的,所以在评估具有不连续性的函数时您必须小心(比如地板)或陡坡。您必须设计代码以接受可能跨越不连续点的结果,或者必须设计计算以避免跨越不连续点的错误。

+0

很好的回答,谢谢 – shox

+0

很好的回答... –

4

你的前两个例子是可以预料的:

  • 8.2 - 0.217.997.99的楼层是7,这就是返回的内容。请记住,floor(x)是小于或等于x的最大整数。 8大于7.99,因此不可能被退回。另一方面,7符合此要求。

  • 8.21 - 0.28.018.01的地板是8 - 这里没有魔法。


>>> math.floor(8.2-0.2) 
7.0 

现在,这是更有趣。它有一个事实,即8.20.2不能准确地用辆彩车代表做,这样计算的结果或许不是你可能有什么想法:

>>> 8.2 - 0.2 
7.999999999999999 

再次,floor()工作as documented

你可以看到这个自己使用decimal为:

>> from decimal import Decimal 
>>> Decimal(0.2) 
Decimal('0.200000000000000011102230246251565404236316680908203125') 
>>> Decimal(8.2) 
Decimal('8.199999999999999289457264239899814128875732421875') 

相关:What Every Computer Scientist Should Know About Floating-Point Arithmetic

+0

@EricPostpischil没关系,你是对的 - 我在想0.8。该错误本身来自“8.2”和“0.2”。我会更新答案。 – arshajii

0

为什么它应该是8?楼层函数返回最近的整数向下舍去,所以这两个例子都是正确的。

8.2 - 0.21 = 7.99,其向下舍入为7

8.21 - 0.2 = 8.01Hz,其向下舍入为8

0
>>> a=0.2 
>>> a 
0.20000000000000001 
>>> b = 8.2 
>>> b 
8.1999999999999993 
>>> b-a 
7.9999999999999991 
>>> math.floor(b-a) 
7.0 

由于浮点不精确