DC娱乐网

一个字段类型选错,赔了两万块 早年做过一个电商结算系统,金额字段用了 doubl

一个字段类型选错,赔了两万块
早年做过一个电商结算系统,金额字段用了 double 类型。测试时一切正常,小数点后两位看不出毛病。上线跑了三个月,财务对账发现差了两万多,一分一厘攒出来的误差,最后我们自己补上。🔥

涉及钱的字段,永远不要用 float 或 double。计算机用二进制存小数,0.1 在二进制里是无限循环小数,只能近似存储,单笔误差极小但订单量大了就累积,对账时根本查不出来。😱

方案一:DECIMAL + BigDecimal

MySQL 用 DECIMAL(18,2) 精确存储,Java 用 BigDecimal 精确运算,计算要调 .add() .multiply() 方法,不能直接用加减运算符。

几个坑:比较用 compareTo() 不要用 equals()(1.0和1.00用equals不相等);构造用字符串或 valueOf(),别用 double 构造;除法必须指定舍入模式,否则除不尽直接抛异常。

方案二:BIGINT 存分

数据库用 BIGINT,单位是分,10.50元就存1050,全程整数运算,没有浮点问题。微信支付、支付宝接口金额单位都是分,展示时除以100格式化就行。

怎么选

BIGINT 存分的优势是整数运算快、跨语言一致、对接支付不用转换,适合电商订单和支付系统。DECIMAL 的优势是小数位数灵活,适合税率、汇率、利率这种需要3位以上小数的场景,但 BigDecimal 运算稍慢、坑也多。

简单说:普通交易金额用存分,复杂小数计算用DECIMAL。不管选哪种,都别用 double。💰

不止是钱,税率、积分、库存量这些要求精确的场景都别用浮点。科学计算、图形渲染、允许误差的统计数据,用 float/double 反而更快。⚡

💡 涉及钱,要么 DECIMAL + BigDecimal,要么 BIGINT 存分。别用 double,别等对账差了两万块才想起来。

你们项目金额用什么存的?评论区聊聊 👇

程序员 MySQL Java BigDecimal 踩坑 后端开发 数据库 电商 支付