繁体   English   中英

使用 DecimalFormat 的 RoundingMode.UP 无法按预期工作

[英]RoundingMode.UP with DecimalFormat does not work as expected

每当有十进制值时,我都会尝试将 Double 数字四舍五入。 我正在尝试以下。 下面的代码片段按预期四舍五入所有其他值。

1.08 -> 2
9.5 -> 10

但将 0.08 舍入为 0 而不是 1。我在这里遗漏了什么吗?

DecimalFormat df = new DecimalFormat("0");
df.setRoundingMode(RoundingMode.UP);
Double number = 0.08;
System.out.println(df.format(number)); // expecting 1 but produces 0
    
number = 1.08;
System.out.println(df.format(number)); // correctly produces 2

这看起来像是针对 JDK8 报告的错误 JDK-8174722的表现,并且仍然以修复版本“tbd”打开(我在 JDK14 上看到了相同的行为)。 在该错误报告中,将0.0001向上舍入到小数点后两位会错误地导致0.00而不是0.01

我试图通过DecimalFormat的源代码来跟踪这个计算,并发现了关于有效数字的多个假设,为了兼容性而保留,但显然是此类问题的原因。 我基于源代码的预感是,如果请求精度之后的第一个数字为 0(或足够接近),则 function 向下舍入。 这种行为与明确说明的文档相反。

如果它很容易修复,我认为链接的错误早就被修复了,但它似乎也是一个低优先级。

正如评论所建议的那样,使用Math.ceil()Math.floor()Math.round()函数将提供更多可预测/一致的结果,并且足以满足大多数用例。

在您的评论中,您建议用户提供RoundingMode ,因此如果您想要直接应用该枚举, 错误报告的 MCVE包含使用BigDecimal.setScale()的解决方法。 @Andreas此评论中发布了此解决方法的应用程序以生成此字符串:

// Note: this ignores Locale
BigDecimal.valueOf(number).setScale(0, RoundingMode.UP).toPlainString();

使用DecimalFormat的另一个选项将允许更改区域设置,并且是:

df.format(BigDecimal.valueOf(number).setScale(0, RoundingMode.UP));

请注意,由于您将在setScale()中使用四舍五入,因此您不需要在DecimalFormat中也使用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM