You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

仅存储不做运算时,Java double类型存储货币值是否总能保持精确?

关于double存储0.00~2.00区间货币值的精度问题解答

核心结论

  • 「0.00到2.00区间的货币值用double存储100%精确」这个结论不成立
  • 直接执行double v = 0.01赋值操作确实存在精度问题

具体原因

  1. double的存储机制决定了它无法精确表示大多数十进制小数
    double是遵循IEEE 754标准的双精度二进制浮点数,本质是用「整数×2的整数次幂」的形式存储数值。而0.01这类两位小数对应的是十进制分数1/100,分母包含质因数5,无法拆解成2的整数次幂的组合,因此从原理上就不可能被二进制浮点数精确表示。你赋值的那一刻,double里存的就是和0.01非常接近的近似值,而非精确的0.01。
    你可以用这段代码直接查看double存储的真实值:
// 直接把double转成无舍入的BigDecimal输出,就能看到完整的存储内容
System.out.println(new BigDecimal(0.01));
// 实际输出:0.01000000000000000020816681711721685132943093776702880859375
  1. 测试输出的全精确结果是格式化工具的假象
    你使用的DecimalFormat默认采用HALF_EVEN(银行家舍入)模式,你设置的小数点后25位的输出规则,刚好把0~2区间两位小数的微小误差给舍入掉了,所以看不到后面的非零位,并非这些值真的存储精确。
  2. 为什么0~2区间的误差看起来不明显?
    双精度浮点数有53位有效二进制位,对应约15~17位十进制有效数字。小于2的数整数部分只占1位二进制位,剩下的位数都用来表示小数部分,所以两位十进制小数的近似误差会非常小,仅做存储、不做运算、且格式化输出位数不足的情况下,很难感知到误差的存在。但这不代表误差不存在,只要对这些值做累加、乘法等运算,误差会快速累积,最终出现明显的计算错误。

场景建议

如果必须对接强制要求用浮点数传输的系统,建议你本地始终用Long(单位:分)或者BigDecimal存储、计算货币值,仅在给外部系统传值的最后一步转成double,接收外部系统的double值后第一时间转回精确类型处理,中间全程不要用double做任何货币运算,能最大程度规避精度问题。

内容的提问来源于stack exchange,提问作者Dreamspace President

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 09:27:05