后台对账,单价 0.1 元、数量 3,页面显示 0.30000000000000004。这不是数据库的错,PHP 的 float 是 IEEE 754 双精度,0.1 在二进制里本来就存不准。换成 bcmul 之后,结果老老实实是 0.30。

三个参数,第三个最容易被忽略

写法是 bcmul(第一个数, 第二个数, 小数位数),前两个参数按字符串传,返回的也是字符串。第三个参数决定保留几位小数,不传就按 bcscale 的全局设置,很多环境默认是 0,59.7 会直接变成 59。比如 19.9 乘 3 保留两位,得到 59.70,末尾的零会保留。它只截断不四舍五入,1.005 保留两位得到 1.00,要四舍五入得自己处理。

报 undefined function 就是扩展没开

页面直接白屏,日志里写 Call to undefined function bcmul(),说明 bcmath 扩展没装。命令行执行 php -m | grep bcmath,没有输出就是没开。Linux 下装 php-bcmath,Windows 下在 php.ini 里把 extension=bcmath 前面的分号去掉,重启 PHP-FPM 或 Apache。用宝塔面板的话,在软件商店对应 PHP 版本的设置里勾选扩展就行。

金额计算别只改乘法

加减乘除要配套用 bcadd、bcsub、bcdiv,乘法也别换回 float,混着用还是会飘。比较大小用 bccomp,它返回 -1、0、1,不能直接当布尔值。数据库存 decimal,取出来也是字符串,正好直接喂给这个函数,别中途转成 float。订单金额建议统一按分存储,显示的时候再除 100,前端就不会看到一长串小数。

大数运算才是它的主场

bcmath 按字符串逐位算,整数超过 15 位以后,float 会丢精度,它不会。循环几十万次它比原生运算慢不少,做报表批量算账时,能放大成整数再算更划算。日常订单、购物车这种量级,这个函数完全够用。

涉及钱和精确小数就用它,第三位小数别省,算完再格式化输出。传进去之前先把字符串洗干净,空值和 null 单独判断。