浮点数因二进制无法精确表示十进制小数(如0.1+0.2=0.30000000000000004),导致==/===比较失效;round或转字符串不能修复底层误差;应改用abs($a-$b)

因为浮点数在计算机中用二进制存储,而像 0.1、0.2、0.3 这类常见十进制小数,在二进制里是无限循环小数,无法精确表示。PHP(和其他所有遵循 IEEE 754 标准的语言)只能存一个近似值。
根本原因:二进制无法精确表达多数十进制小数
例如:
-
0.1 + 0.2实际结果是0.30000000000000004,不是精确的0.3 -
0.58 * 100得到的是57.99999999999999,而非58.0 - 这些误差是存储层面的,不是计算错误,也无法靠“多算几步”修复
== 比较会暴露这个误差
== 和 === 做的是**完全相等判断**,只要内存中的两个 float 值不完全一致,就返回 false:
var_dump(0.1 + 0.2 == 0.3); // bool(false)- 哪怕肉眼看着一样,底层比特位不同,比较就失败
- 这种失效在满减判断、库存扣减、支付校验等业务逻辑中,会直接导致分支跳过或误触发
round() 或 string 强转也不能救
这些操作作用于已经失真的 float 值,属于“在错误基础上再加工”:
-
round(0.1 + 0.2, 1)得到0.3,但这是四舍五入后的显示值,原始计算仍不准 -
(string)(0.1 + 0.2)可能变成"0.30000000000000004",反而把误差暴露给后续处理 - 用
round($a, 2) == round($b, 2)判断相等,选错精度位数就会翻车
真正靠谱的做法不是“修浮点数”,而是换思路
根据场景选择合适方式:
- 要判断“是否足够接近” → 用
abs($a - $b) (如 <code>1e-6或1e-9) - 要判断“金额是否够扣”“配置是否达标”这类确定性逻辑 → 用
bccomp('19.99', '20.00', 2),且输入必须是字符串 - 做金额运算本身 → 用
bcadd('19.99', '0.01', 2),全程避开 float - 数据库存金额 → 必须用
DECIMAL(10,2),不能用FLOAT或DOUBLE
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











