这是浮点行为还是PHP中的错误


Is this floating point behavior or a bug in PHP?

澄清:这并不是问我为什么会出现舍入错误。我知道这是一个错误或疏忽。问题是,为什么它在第一个var_dump中整体打印,但铸造的行为就好像它是57916.9重复,并截断了所说的.9重复。

出现以下情况:

取一个包含值579.17的字符串(或float——无关紧要),并将其乘以100。它var_dumps预期的57917。不是57916.999999999999999999999或类似的。在我看来,var_dump不应该作为调试函数来舍入任何内容。它可能必须截断,但舍入在调试函数中是意外的。

但是,如果将其强制转换为整数,则会从var_dump中得到意外的57916。

我知道浮点数字的问题,但在PHP中投射一个打印为57917的浮点数字的行为显然有效地减去了1。这是一个非常小的数字。

这种情况似乎只发生在某些数字上,比如579.17。我测试过的其他人不会出现这种情况。我们所要做的就是将一个数字乘以100,发送到一个预期为美分的API。API库可以理解地强制转换为整数,因为API不接受分数美分。

测试用例:

php -r '$n = ("579.17" * 100); var_dump($n, (int)$n);'

输出:

float(57917)
int(57916)

环境:

x86-32,
x86-64 both.

var_dump使用php.ini中的precision来显示浮点值。你可以把它举起来看看会发生什么。

php -r 'ini_set("precision", 20); $n = ("579.17" * 100); var_dump($n, (int)$n);'
// double(57916.999999999992724)
// int(57916)

此外。没有x86或x64。PHP使用64位作为浮点值。

http://php.net/manual/en/language.types.float.php

使用round()而不是int()579.17 * 100的实际值类似于57916.99999var_dump()将其显示为57917,但当使用int()时,它会截断分数。使用round()将转到最接近的整数,而不是总是向下截断。

我相信这是因为硬件无法真实准确地表达浮点数。所以看起来是579.17,实际上更像是579.16999999。因此,当你把它相乘并转换为int时,它会截断小数,留下57916。