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

Java DecimalFormat特定场景下格式化异常原因咨询

关于Java DecimalFormat格式化double的异常问题分析

问题现象

第一组异常案例

// 如预期返回"0.1"
(new DecimalFormat("0.#", new DecimalFormatSymbols(Locale.US))).format(0.05); 

// 如预期返回"0.01"
(new DecimalFormat("0.##", new DecimalFormatSymbols(Locale.US))).format(0.005); 

// 预期返回"0.001",实际返回"0"
(new DecimalFormat("0.###", new DecimalFormatSymbols(Locale.US))).format(0.0005);

// 预期返回"0.0001",实际返回"0"
(new DecimalFormat("0.####", new DecimalFormatSymbols(Locale.US))).format(0.00005); 

为何第三、四条语句返回"0"?

第二组异常案例

// 如预期返回"1.105"
(new DecimalFormat("#.###")).format(1.1045);

// 预期返回"0.105",实际返回"0.104"(原因何在?)
(new DecimalFormat("#.###")).format(0.1045); 

核心原因:double类型的精度丢失

Java中的double是IEEE 754标准的双精度浮点数,它无法精确表示所有十进制小数,只能存储近似值:

  • 像0.0005这样的小数,实际在内存中存储的近似值是0.0004999999999999999...,比真实值略小;当用0.###格式(保留三位小数)格式化时,第四位小数是4,触发舍去操作,最终得到0.000,显示为"0"。同理0.00005的存储值更小,格式化后也会显示"0"。
  • 对于1.1045和0.1045,两者的存储近似值不同:1.1045实际存储为1.1045000000000002...(略大于真实值),格式化到三位小数时会进一位得到1.105;而0.1045实际存储为0.10449999999999999...(略小于真实值),格式化时舍去第四位的4,得到0.104。

解决方案:使用BigDecimal避免精度问题

要彻底解决这类问题,应该用BigDecimal来替代double,它可以精确表示十进制小数:

// 方式1:用字符串构造BigDecimal(推荐,避免double转BigDecimal时的精度问题)
BigDecimal num1 = new BigDecimal("0.0005");
BigDecimal num2 = new BigDecimal("0.1045");

// 方式2:如果必须从double转换,使用BigDecimal.valueOf()
BigDecimal num3 = BigDecimal.valueOf(0.0005);

// 格式化示例
DecimalFormat df = new DecimalFormat("0.###", new DecimalFormatSymbols(Locale.US));
System.out.println(df.format(num1)); // 输出"0.001"
System.out.println(df.format(num2)); // 输出"0.105"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 21:42:25