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

Java DecimalFormat四舍五入异常:14.3445格式化结果不符预期

为什么DecimalFormat格式化14.3445得到14.34而不是14.35?

嘿,这个问题其实藏着两个容易踩坑的点:浮点数精度限制和DecimalFormat默认的舍入规则,还有你对舍入逻辑的小误解,咱们一个个说清楚:

1. 你的分步舍入逻辑是错的

首先纠正一个认知:DecimalFormat不会像你想的那样先把14.3445转成14.345(三位小数),再转成14.35(两位小数)。它是直接对原始数值进行舍入,保留到指定的两位小数——也就是说,它会看第三位小数的数值及后面的部分,直接判断是否进位,不会做中间过渡步骤。

2. 14.3445作为double类型,并不是精确的14.3445

这是关键问题!十进制的14.3445无法用二进制浮点数(也就是Java里的double)精确表示,实际存储在内存里的是一个略小于14.3445的近似值。你可以用BigDecimal来打印这个精确值验证:

System.out.println(new BigDecimal(14.3445));

输出大概是:

14.3444999999999994315658113919198513031005859375

看到没?这个实际值比14.3445还小一点,更别说达到14.345了。所以当你用DecimalFormat保留两位小数时,它处理的是这个近似值,自然会得到14.34。

3. DecimalFormat默认用的是「银行家舍入法」

就算我们假设数值是精确的14.3445,DecimalFormat默认的舍入模式是RoundingMode.HALF_EVEN(银行家舍入法),不是我们日常用的「四舍五入」(RoundingMode.HALF_UP)。这种舍入规则是:如果舍去部分的最高位是5,且前一位是偶数,就舍去;如果前一位是奇数,才进位。不过在这个案例里,因为第三位小数是4,不管哪种舍入模式都会舍去,所以这一点不是这次问题的主要原因,但也是你需要了解的知识点。

怎么得到你预期的14.35?

要解决这个问题,你需要同时解决浮点数精度和舍入模式两个问题:

方法一:用BigDecimal存储精确的十进制数,再设置正确的舍入模式

// 用字符串创建BigDecimal,保证数值精确
BigDecimal num = new BigDecimal("14.3445");
DecimalFormat df2 = new DecimalFormat(".00");
// 设置为传统四舍五入模式
df2.setRoundingMode(RoundingMode.HALF_UP);
System.out.println(df2.format(num)); // 输出14.35

方法二:直接用BigDecimal的setScale方法

如果不需要格式化字符串,只是需要数值计算后的结果,直接用BigDecimal的舍入更简单:

BigDecimal num = new BigDecimal("14.3445");
BigDecimal result = num.setScale(2, RoundingMode.HALF_UP);
System.out.println(result); // 输出14.35

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:08:56