[花了一个小时试图找出为什么PHP脚本给我错误输出后,结果发现在特定情况下,循环短了一个迭代。为说明发生了什么:从XML属性读取版本号(两位数,例如1.5或2.0),然后乘以100。脚本随后在已定义的版本号倍数范围内进行迭代。
事实证明,410 == 409
,如果您将一个以10为步长递增的计数器与该值进行比较,会带来一个有趣的惊喜。
这使我想到了一个问题:我从根本上理解错了吗?当然,4.1
,100
和410
应该都可以很好地表示为float,并且应该可以很好地转换为int且没有舍入错误吗?
但是,在我的系统上(使用PHP 5.3.2 CLI,Zend Engine 2.3.0),以下测试用例
<?
$a = 100 * 4.1;
$b = (string) $a;
$c = (int) $a;
$d = (int)(string) $a;
var_dump($a);
var_dump($b);
var_dump($c);
var_dump($d);
?>
输出:
float(410)
string(3) "410"
int(409)
int(410)
我现在正在执行(int)(string)
转换,该转换有效,但这是一种讨厌的骇客,它不美观且感觉不太正确。是否有更好的(正确的,没有hack的)解决方案来获得准确的结果?
您通常看不到,是否仅通过查看就可以将其很好地转换为浮点数。阅读The warning in the manual为例。
您的问题在第一行:
$a = 100 * 4.1;
浮点文字4.1
does not, in fact, have the value 4.1,因此将其乘以100的结果不是410,而是少了一点。显然,强制转换为字符串取整,但是强制转换为int取整。
要获得期望的十进制数学,请使用BC Math函数。
您可以使用BC数学函数来获得浮点乘法的可预测结果
http://php.net/manual/en/ref.bc.php
intval(4.1 * 100) === 409
bcmul(4.1, 100) === '410'
尝试使用intval
$c = intval($a);
编辑:
尝试使用普通舍入将其舍入:
$c = round($a, 0, PHP_ROUND_HALF_UP);
如您所见,与4.1的乘法将返回浮点数。将float转换为int会执行floor()之类的操作,这意味着,如果结果为409.999 ...,它将返回409。如果要使用整数,则不应在计算中混用float和整数值,或者您应该随后使用round()来获取最接近的整数。
精确表示的可能值为0.5、0.25、0.125,这是通过除以2可获得的值,因为该值存储在二进制系统中。
我用它来解决问题:
round($a);