PHP中令人惊讶的float-int转换

|| 在花了一个小时试图找出为什么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)
转换,但效果不错,但这是一个讨厌的骇客,它不美观也不十分正确。 是否有更好的(正确的,没有漏洞的)解决方案来获得准确的结果?     
已邀请:
您通常看不到值是否仅通过查看就可以很好地转换为浮点数。请阅读手册中的警告作为示例。     
您的问题在第一行:
$a = 100 * 4.1;
浮点字面量
4.1
实际上没有值4.1,因此将其乘以100的结果不是410,而是少一点。显然,强制转换为字符串取整,但是强制转换为int取整。 要获得期望的十进制数学,请使用BC Math函数。     
您可以使用BC数学函数来获得浮点乘法的可预测结果 http://php.net/manual/zh/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所得的值,因为该值存储在二进制系统中。     

要回复问题请先登录注册