电商金额计算必须统一转为整数(分)运算:输入立即乘100转int/long,禁用浮点字面量和double中间变量,数据库用decimal,除法用bigdecimal舍入,强制转换需校验溢出与精度。

电商系统中金额计算必须精确到“分”,不能依赖浮点数直接运算。强制类型转换本身不解决精度问题,但配合整数化策略和二进制底层意识,可构建稳定可靠的分币处理链路。
把金额统一转为整数(分)再运算
核心原则:所有金额输入立即乘100并转为整型(如 int 或 long),彻底规避小数二进制表示缺陷。例如用户输入“¥19.99”,系统不做 double price = 19.99,而是解析字符串后提取数字:
- 用正则或字符串分割获取“19”和“99”,拼接为整数 1999
- 或使用安全解析函数(如 Java 的
BigDecimal("19.99").multiply(BigDecimal.ONE_HUNDRED).intValueExact()) - 后续加减乘除全部在整数域完成,结果再按需转回“元.分”格式展示
理解二进制限制,避免隐式浮点参与
即使写了 (int)(19.99 * 100),也存在风险——因为 19.99 作为字面量在编译时可能已失真(如实际存为 19.989999999999998)。所以:
- 禁止用浮点字面量参与金额计算,尤其避免
double类型中间变量 - 前端传参建议用字符串或整数(单位:分),后端不做“字符串→double→int”链式转换
- 数据库字段必须用 DECIMAL(10,2) 或等效类型,而非 FLOAT/DOUBLE
关键环节的强制转换要带校验
强制类型转换不是万能钥匙,粗暴转 (int)doubleValue 可能截断、溢出或因精度偏差导致错误结果。正确做法是:
- 优先使用带异常的安全转换,如 Java 的
Math.toIntExact(long)或BigInteger.intValueExact() - 对超范围值明确拒绝(如单笔订单 > 21 亿元就报错,而不是静默取模)
- 涉及除法时,用
BigDecimal.divide(..., RoundingMode.HALF_UP)控制舍入,不依赖整数除法自动截断
二进制视角下的边界测试不可少
虽然业务层用整数,但底层存储、网络序列化、日志打印仍可能暴露二进制表现。建议在关键路径加入:
- 对“分”值做二进制位宽检查(如确保 long 类型下不超过 2⁶³−1,即约 922 亿分 ≈ ¥9.22 亿元)
- 用十六进制或二进制字符串打印调试值,确认无意外符号位或高位污染
- 模拟 IEEE 754 边界值(如 0.1、0.2、0.3)做反向注入测试,验证系统是否真正隔离了浮点路径











