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

Java DecimalFormat保留1位小数时9.85与9.95舍入结果不一致问题

问题核心原因

你遇到的不一致表现是两个因素共同导致的:double类型的浮点数精度丢失,以及DecimalFormat默认的舍入模式规则。


1. 浮点数精度问题

Java中9.85、9.95这类直接写的字面量默认是double类型,属于二进制浮点数,无法精确表示所有十进制小数,你以为传入的是精确的十进制值,实际JVM存储的值和预期有偏差:

  • 你写的9.85实际存储的double值约为9.8499999999999996447286321199499070644378662109375,比真实的9.85略小
  • 你写的9.95实际存储的double值约为9.9500000000000010658141036401502788066864013671875,比真实的9.95略大

你可以直接用System.out.println(new BigDecimal(9.85))打印验证实际存储的数值。


2. DecimalFormat默认舍入规则

DecimalFormat默认使用RoundingMode.HALF_EVEN(银行家舍入法),规则为:

  • 当舍去部分的最高位小于5时直接舍去
  • 当舍去部分的最高位大于5时向前一位进1
  • 当舍去部分的最高位恰好是5时,若前一位是偶数则舍去,是奇数则进1

对应测试用例的解释

  • 用例1:new DecimalFormat("#.#").format(9.85)
    传入的实际值略小于9.85,保留1位小数时舍去部分不足0.05,所以直接舍去得到9.8
  • 用例2:new DecimalFormat("#.#").format(9.86)
    9.86的double存储值和真实值偏差极小,舍去部分大于0.05,触发进1得到9.9
  • 用例3:new DecimalFormat("#.#").format(9.95)
    传入的实际值略大于9.95,保留1位小数时舍去部分大于0.05,触发进1,9.9+0.1等于10,最终输出10
  • 用例4:new DecimalFormat("#.#").format(9.96)
    数值本身足够大,进1后得到10,符合预期

解决方案

如果要完全避免浮点数精度带来的舍入异常,建议不要直接传入double类型做格式化,改用BigDecimal传递精确的十进制值,同时明确指定你需要的舍入模式:

// 示例:指定四舍五入模式,使用字符串构造BigDecimal保证精度
DecimalFormat df = new DecimalFormat("#.#");
df.setRoundingMode(RoundingMode.HALF_UP); // 明确设置为普通四舍五入模式
String res1 = df.format(new BigDecimal("9.85")); // 输出9.9
String res2 = df.format(new BigDecimal("9.95")); // 输出10.0

内容的提问来源于stack exchange,提问作者Pranesh Sahu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 02:54:01