PHP中40.05*100结果转int比预期少1问题求助
问题成因
这个问题本质是浮点数精度丢失的通用问题,并非PHP独有,所有遵循IEEE 754浮点数标准的编程语言都存在类似情况:
- 十进制的40.05无法被二进制浮点数精确表示,实际存储的是一个接近40.05但略小于它的近似值,乘以100之后得到的结果也不是精确的4005,而是近似为
4004.999999999999这类略小于4005的数值 - PHP中
(int)转换的规则是直接截断小数部分,不会做四舍五入,所以会把4004.999999999999直接取整为4004 - 直接打印
40.05 * 100得到4005是因为PHP的输出默认会做隐式的精度 rounding,把非常接近整数的浮点数近似显示为整数,掩盖了实际存储的精度误差
解决方案
根据使用场景可以选择以下几种处理方式:
- 普通数值转换场景,用
round()函数先做四舍五入再转int
// 正确得到4005 $result = (int) round(40.05 * 100);
- 涉及金额、统计等对精度要求高的场景,优先用BC Math高精度函数处理,避免浮点数误差
// 先把数值转为字符串类型传入bcmul,计算结果再转int $result = (int) bcmul('40.05', '100');
- 金额类固定精度的业务场景,可以直接把单位转换为最小单位(如分)之后用整数存储,全程避免浮点数运算,从根源上杜绝精度问题
内容的提问来源于stack exchange,提问作者Culky
相关产品推荐
相关产品推荐

