你还在用intval四舍五入?小心掉坑

话说有一天,我在写一个电商网站的订单结算逻辑,需要把商品价格转换成整数,因为我们的系统只支持整数金额。于是我就很自然地想到了 php 的 intval 函数。但后来我发现,事情没那么简单。

先说下 intval 的基本用法。这函数就是把变量转换成整数,支持第二个参数指定进制,默认是10进制。比如 intval('42') 返回42,intval('0x2A') 返回42,intval('101010', 2) 返回42。

但当我用 intval(4.6) 想四舍五入时,发现返回的是4,而不是我预期的5。这才知道 intval 是直接截断小数部分,不会四舍五入。于是我就改成了 round(4.6),这下返回了5。

但还没完,当我用 round(4.5) 时,发现返回的竟然是4,而不是我预期的5。这让我一脸懵逼。查了下文档,才知道 round 函数默认使用的是"银行家舍入法",也就是当值为5时,会选择最接近的偶数。于是我又改成了 round(4.5, 0, PHP_ROUND_HALF_UP),这才得到我预期的5。

正当我以为问题都解决了时,又遇到一个新问题。当我把浮点数转换成整数时,有时会得到意想不到的结果。比如:

echo intval(19.99 100);

你猜会输出什么?1999?不对,是1998。这是因为浮点数在计算机中是以二进制存储的,存在着精度问题。19.99 100 实际上存储的是 1998.9999999999998。

要解决这个问题,我需要在转换之前先四舍五入:

这下就得到了预期的1999。

但这还没完,还有一个隐藏的坑。当处理大整数时,intval 会截断超出范围的值。比如在32位系统上,intval('999999999999') 会返回2147483647。要避免这个问题,我需要在转换之前先检查是否超出范围:

if (is_numeric($value) && $value <= PHP_INT_MAX && $value >= PHP_INT_MIN) {

$intValue = intval($value);

} else {

// 处理超出范围的情况

}

说到这,你可能会问,那为什么不直接用 round 就好了,还要用 intval?这是因为 round 返回的还是浮点数,不能保证是整数。比如 round(4.6) 返回的是 float(5),而不是 int(5)。所以如果严格需要整数的话,还是得用 intval。

最后总结一下,把 float 转换成 int 时正确的姿势是:

$intValue = intval(round($floatValue));

或者如果是要四舍五入到指定小数位,再转换成整数:

$intValue = intval(round($floatValue, $decimalPlaces));

但要记住处理浮点数精度和整数范围的问题。

以上就是我在使用 php 的 intval 和 round 函数时踩过的坑和总结的经验。希望对你有所帮助,少踩点坑。当然,还有更复杂的情况我没遇到,如果你知道的话,欢迎补充。毕竟,程序员不就是每天在debug和踩坑中度过的吗?生活不止眼前的bug,还有远方的bug在等着我们。但只要我们有一颗热爱技术的心,就没有解决不了的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值