浮点数行为

时间:2013-07-03 17:34:42

标签: php numbers floating-accuracy

我的室友提出了一个问题。

为什么在php(也许是其他语言)floor($foo)(int)$foo是7?

$foo = (0.7 + 0.1) * 10;
var_dump(
    $foo,
    floor($foo),
    (int)$foo,
    ceil($foo),
    is_infinite($foo),
    is_finite($foo));

结果

float(8)
float(7)
int(7)
float(8)
bool(false)
bool(true)

请注意$foo不是无限数。

从答案中我可以看到每个人都说它实际上是x.(9)

数字为x.(9)背后的原因是什么,而不是实际的x ,因为它应该在现实生活中?

4 个答案:

答案 0 :(得分:1)

并非总是如此。如果由于浮点不精确而最终得到8.0000001,则地板将会捕捉到8.有时它可能是7.999999,它将捕捉到7。

如果您将0.x乘以y(在大多数语言中读取为int),则可能会出现整数,因此您不会看到此行为。

这在其他语言中也是如此。

答案 1 :(得分:1)

因为0.7和/或0.1内部实际上是0.6999999 ....或0.09 .....

这意味着你的(0.7 * 0.1)更像是0.7999 .....在乘以10和int /地板后,你最终得到7。

答案 2 :(得分:1)

floor函数向下舍入到最接近的整数。转换为int只会丢弃小数部分。 $foo是一个浮点数,它不是完全 8,(必须是7.99999 ...)所以你可以观察到这种行为。

答案 3 :(得分:1)

如果分母包含不在基数素数列表中的素数因子(即2和5),则有理数将变为重复小数

  
      
  • 如果减少分数的分母包含不是基数因子的素因子,则有理数具有无限重复的有限长度序列,小于完全减少分数分母的值。如果减少的分数也与基数共享一个素数因子,那么重复序列在小数点之后是有限长度的瞬态。
  •   
     

https://en.wikipedia.org/wiki/Repeating_decimal

计算机中的浮点类型几乎总是二进制的,因此任何在有理表示中的分母不是2的幂的数将是无限的周期小数。例如,0.1将在0.100000001490116119384765625中四舍五入为IEEE-754 single precision,这是最近的2s幂之和

这里,0.7和0.1都不能用二进制浮点表示,也不是0.8。它们的总和也不等于0.8:尝试打印0.7 + 0.1 == 0.8,你会得到错误的结果。它实际上略小于0.8。但它是重复小数,如7.(9),但是小数部分中有限数量为9的值。

因此,ceilint会产生7.如果您获得floorround结果,则会获得8