推荐使用bigdecimal,因其能避免浮点数精度丢失,在金融等高精度场景中不可替代;它以整数+标度方式存储十进制数,支持8种可控舍入模式,且必须通过字符串初始化才能保证精度。

推荐使用 BigDecimal,核心原因是它能避免浮点数运算中的精度丢失,尤其在金融、财务、税务等对小数准确性零容忍的场景中,这是不可替代的关键优势。
精度可控,不依赖二进制表示
float 和 double 是基于二进制存储的,而很多十进制小数(比如 0.1、0.05)在二进制中是无限循环小数,必须截断,导致天然精度缺陷。例如:
- 0.1 + 0.2 == 0.30000000000000004(double 运算结果)
- BigDecimal("0.1").add(BigDecimal("0.2")) 得到精确的 0.3
BigDecimal 内部用整数+标度(scale)的方式表示十进制数,从源头上规避了二进制转换误差。
舍入行为完全可指定
浮点数运算没有舍入控制权,而 BigDecimal 提供 8 种标准舍入模式,比如:
- RoundingMode.HALF_UP:常规四舍五入(金融计价常用)
- RoundingMode.HALF_EVEN:银行家舍入(大量统计时更公平)
- RoundingMode.DOWN:直接截断(如手续费封顶)
每次除法、设定小数位数都必须显式传入 scale 和 roundingMode,强制开发者思考“这里该怎样舍入”,减少隐式错误。
初始化方式决定精度是否真实
构造 BigDecimal 时,绝不能用 double 字面量直接构造,因为传入前精度已丢失:
- ❌
new BigDecimal(0.1)→ 实际是0.10000000000000000555... - ✅
new BigDecimal("0.1")或BigDecimal.valueOf(0.1)→ 精确等于 0.1
数据库字段映射、前端传参转 BigDecimal 时,务必走字符串路径,避免“以为用了 BigDecimal 就安全”的假象。
适合高可靠业务场景
不只是“能算准”,更是为关键业务提供确定性保障:
- 金额计算:账户余额、利息、分账、发票税额
- 科学数据:实验测量值、工程系数(需固定小数位)
- 规则引擎:风控阈值、比例配置(如“费率=0.0035”必须严格生效)
它的不可变性、明确的 scale 控制、丰富的比较与格式化 API,让业务逻辑更清晰、审计更可信、问题更容易复现。










