Java中使用DecimalFormat保留两位小数的舍入异常问题
Double类型四舍五入精度问题解决
问题根源
Double是二进制浮点数类型,50.275这个十进制小数无法被二进制精确表示,它实际在内存中存储的是一个略小于50.275的近似值(比如50.274999999999996)。DecimalFormat基于这个近似值做四舍五入,自然会得到50.27,而非你预期的50.28,换HALF_EVEN模式也没用,因为底层数值本身就不对。
可行解决方案
方案1:用BigDecimal精确处理(推荐)
直接用字符串构造BigDecimal,避免Double转BigDecimal时的精度丢失,再指定小数位数和舍入模式:
import java.math.BigDecimal; import java.math.RoundingMode; public class RoundingUtil { public static String formatToTwoDecimal(double value) { // 用字符串构造BigDecimal,保留原始数值精度 BigDecimal decimal = new BigDecimal(String.valueOf(value)); // 保留两位小数,使用HALF_UP舍入 return decimal.setScale(2, RoundingMode.HALF_UP).toString(); } public static void main(String[] args) { System.out.println(formatToTwoDecimal(50.275)); // 输出:50.28 } }
方案2:调整DecimalFormat的输入(不推荐,但可应急)
如果一定要用DecimalFormat,先把Double转成精确的BigDecimal再传入格式化:
import java.text.DecimalFormat; import java.math.BigDecimal; import java.math.RoundingMode; public class DecimalFormatFix { public static String formatValue(double value) { DecimalFormat df = new DecimalFormat("0.00"); df.setRoundingMode(RoundingMode.HALF_UP); // 先转成精确的BigDecimal再格式化 return df.format(new BigDecimal(String.valueOf(value))); } public static void main(String[] args) { System.out.println(formatValue(50.275)); // 输出:50.28 } }
关键提示
- 涉及精确计算(比如金额、统计数据)的场景,别用Double/Float类型存储数值,直接用BigDecimal更靠谱。
- 不要依赖Double的十进制字面量做精确运算,二进制浮点数的精度限制会让你踩很多坑。
内容的提问来源于stack exchange,提问作者Mr.Simple
相关产品推荐
相关产品推荐

