导出对账单,金额列显示 1234.5,客户回邮件说少了两位。代码里写的是 number_format($amount),看着像保留了小数,实际第二个参数没传,默认按整数处理。

number_format 的参数顺序是:数字、保留小数位、小数点符号、千分位符号。只传第一个参数时,会四舍五入到整数并加千分位逗号,所以 1234.5 变成 1,235。这就是很多人第一次被它坑到的地方,输出看着还挺规整,问题就被忽略了。

正确写法

echo number_format(1234.5, 2, '.', ','); // 输出 1,234.50

第三个参数是小数点,第四个是千分位。要做欧洲格式,把两者反过来传,变成 1.234,50。别小看这个,跨境业务里搞错,发票金额会被对方财务直接退回,来回沟通一轮就是好几天。

几个必须知道的细节

  • 返回值是字符串:再参与计算会被转成数字,带千分位逗号时结果可能出乎意料
  • 四舍五入:按 PHP 的 round 规则处理,遇到 .5 向上,负数方向要单独测一遍
  • 浮点误差:0.1 加 0.2 不等于 0.3,金额计算建议用 bcadd 或者按分存整数
  • 负数:会输出 -1,234.50,符号在最前面,不会跑到括号里

参数之间别写错顺序。有人把小数点写在千分位的位置,结果 1234.5 变成 1.234,50,本地测试没发现,因为两边都用了逗号,看着还算对。

还有个常见需求是金额转大写,number_format 做不到,得自己写映射或者用现成库。规则多,角分进位、零的处理、整元加整,写错一次就是财务事故,别在这上面硬凑。

顺便说一句,intl 扩展的 NumberFormatter 也能做同样的事,还能按地区自动选格式。要处理多语言站点,用它比手写参数省心;只做人民币展示,number_format 足够了。展示用格式化函数,计算用整数分或者 bc 系列,两条路分开走。