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

问题描述 投票:1回答:6

[花了一个小时试图找出为什么PHP脚本给我错误输出后,结果发现在特定情况下,循环短了一个迭代。为说明发生了什么:从XML属性读取版本号(两位数,例如1.5或2.0),然后乘以100。脚本随后在已定义的版本号倍数范围内进行迭代。

事实证明,410 == 409,如果您将一个以10为步长递增的计数器与该值进行比较,会带来一个有趣的惊喜。

这使我想到了一个问题:我从根本上理解错了吗?当然,4.1100410应该都可以很好地表示为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的)解决方案来获得准确的结果?

php floating-point type-conversion
6个回答
2
投票

您通常看不到,是否仅通过查看就可以将其很好地转换为浮点数。阅读The warning in the manual为例。


3
投票

您的问题在第一行:

$a = 100 * 4.1;

浮点文字4.1 does not, in fact, have the value 4.1,因此将其乘以100的结果不是410,而是少了一点。显然,强制转换为字符串取整,但是强制转换为int取整。

要获得期望的十进制数学,请使用BC Math函数。


3
投票

您可以使用BC数学函数来获得浮点乘法的可预测结果

http://php.net/manual/en/ref.bc.php

intval(4.1 * 100) === 409
bcmul(4.1, 100) === '410'

2
投票

尝试使用intval

$c = intval($a);

编辑:

尝试使用普通舍入将其舍入:

$c = round($a, 0, PHP_ROUND_HALF_UP);

1
投票

如您所见,与4.1的乘法将返回浮点数。将float转换为int会执行floor()之类的操作,这意味着,如果结果为409.999 ...,它将返回409。如果要使用整数,则不应在计算中混用float和整数值,或者您应该随后使用round()来获取最接近的整数。

精确表示的可能值为0.5、0.25、0.125,这是通过除以2可获得的值,因为该值存储在二进制系统中。


0
投票

我用它来解决问题:

round($a);
© www.soinside.com 2019 - 2024. All rights reserved.