Java NumberFormat 舍入模式,为啥一半格式 1.015 到 1.01 而不是 1.02

Posted

技术标签:

【中文标题】Java NumberFormat 舍入模式,为啥一半格式 1.015 到 1.01 而不是 1.02【英文标题】:Java NumberFormat rounding mode, why half up format 1.015 to 1.01 not to 1.02Java NumberFormat 舍入模式,为什么一半格式 1.015 到 1.01 而不是 1.02 【发布时间】:2019-10-31 01:58:19 【问题描述】:

Java 代码

@Test
void a() 
    NumberFormat format = DecimalFormat.getInstance(Locale.CHINA);
    format.setMaximumFractionDigits(2);
    format.setMinimumFractionDigits(2);
    format.setCurrency(Currency.getInstance(Locale.CHINA));
    for (RoundingMode mode : RoundingMode.values()) 
        if(mode == RoundingMode.UNNECESSARY) continue;
        format.setRoundingMode(mode);
        System.out.println("Rounding mode: " + mode);
        System.out.println("--------------------------------------------------------");
        System.out.println("\t format 1.014 is " + format.format(1.014));
        System.out.println("\t format 1.015 is " + format.format(1.015));
        System.out.println("\t format 1.016 is " + format.format(1.016));
        System.out.println();
    

结果:

舍入模式:UP

 format 1.014 is 1.02
 format 1.015 is 1.02
 format 1.016 is 1.02

舍入模式:DOWN

 format 1.014 is 1.01
 format 1.015 is 1.01
 format 1.016 is 1.01

舍入模式:CEILING

 format 1.014 is 1.02
 format 1.015 is 1.02
 format 1.016 is 1.02

舍入模式:FLOOR

 format 1.014 is 1.01
 format 1.015 is 1.01
 format 1.016 is 1.01

舍入模式:HALF_UP

 format 1.014 is 1.01
 format 1.015 is 1.01
 format 1.016 is 1.02

舍入模式:HALF_DOWN

 format 1.014 is 1.01
 format 1.015 is 1.01
 format 1.016 is 1.02

舍入模式:HALF_EVEN

 format 1.014 is 1.01
 format 1.015 is 1.01
 format 1.016 is 1.02

进程以退出代码 0 结束

那么,有没有一种简单的方法可以将 1.015 格式化为 1.02?(JDK 12,JDK 8)

【问题讨论】:

【参考方案1】:

那是因为 1.015 实际上是 1.0149999999999999023003738329862244427204132080078125

使用 BigDecimal 的解决方案适用于字符串

BigDecimal db = new BigDecimal("1.015");
db = db.setScale(2, BigDecimal.ROUND_HALF_UP);`

【讨论】:

【参考方案2】:

使用舍入模式:CEILING(向上舍入)

public static Double roundUp(double n, int decimalPlace) 
    BigDecimal instance = new BigDecimal(Double.toString(n));
    return instance.setScale(decimalPlace, RoundingMode.CEILING).doubleValue();

例如:roundUp(1.014, 2) --> 1.02

【讨论】:

以上是关于Java NumberFormat 舍入模式,为啥一半格式 1.015 到 1.01 而不是 1.02的主要内容,如果未能解决你的问题,请参考以下文章

为啥 NumberFormat 中需要以下 2 种方法?

BigDecimal的精度舍入模式详解

java BigDecimal八种舍入模式

Java中BigDecimal的8种舍入模式是怎样的

为啥 Android 的 NumberFormat 使用逗号作为澳大利亚的小数分隔符?

Java 详解数字格式化(NumberFormat&DecimalFormat)