几种语言的int((0.1 + 0.7)* 10)= 7。怎么预防这个?

时间:2011-06-22 11:36:25

标签: php javascript python ruby internal-representation

最近我遇到了几种语言的错误/功能。我对它是如何引起的有一个非常基本的了解(我想要一些详细的解释),但是当我想到多年来我必须犯下的所有错误时,问题是如何确定“ 嘿,这可能会导致一个荒谬的bug,我最好使用任意精确函数 “,其他语言确实有这个bug(而那些没有,为什么)。另外,为什么0.1 + 0.7这样做,而0.1 + 0.3不这样做,还有其他众所周知的例子吗?

PHP

//the first one actually doesn't make any sense to me,
//why 7 after typecast if it's represented internally as 8?
debug_zval_dump((0.1+0.7)*10); //double(8) refcount(1)
debug_zval_dump((int)((0.1+0.7)*10)); //long(7) refcount(1)
debug_zval_dump((float)((0.1+0.7)*10)); //double(8) refcount(1)

的Python:

>>> ((0.1+0.7)*10)
7.9999999999999991
>>> int((0.1+0.7)*10)
7

使用Javascript:

alert((0.1+0.7)*10); //7.999999999999999
alert(parseInt((0.7+0.1)*10)); //7

红宝石:

>> ((0.1+0.7)*10).to_i                                                  
=> 7                                                                    
>>((0.1+0.7)*10)                                                       
=> 7.999999999999999                                                    

7 个答案:

答案 0 :(得分:32)

答案 1 :(得分:7)

这不是语言问题。这是float point arithmetic的一般问题。

答案 2 :(得分:5)

Stop using floats。不,真的。

答案 3 :(得分:3)

floating point representation of numbers is not exact

在Python中,int截断浮动朝零到最接近的整数。 PHP中为(int),Javascript中为parseInt,Ruby中为to_i也是如此。

这不是一个错误;这就是这些功能的运作方式。

例如,来自the docs的Python int

  

浮点数的转换   整数截断(朝零)。

答案 4 :(得分:1)

这是一个与浮点表示有关的已知问题,您可以在此处找到更多信息:

http://en.wikipedia.org/wiki/IEEE_754-2008

具体问题是7.9将直接转换(截断)为7,同时将其转换为int。在Python中,您可以使用以下方法解决此问题:

int( round(((0.1+0.7)*10)) )

......和其他语言类似。

但是,在许多情况下,这可能是一个问题。例如,浮点数对于工资单程序来说不够可靠。

也许其他人可以给你其他提示。无论如何,Hpe有帮助。

答案 5 :(得分:1)

使用decimal模块:

>>> int((decimal.Decimal('0.1')+decimal.Decimal('0.7'))*10)
8

答案 6 :(得分:0)

PHP默认使用浮点数,您需要手动转换为整数。

您应该了解浮点运算。这里的其他帖子提供了足够的链接。

我个人使用round / ceil / float取决于我期望的而不是int

$a = (int) round((0.7 + 0.1) * 10);