Java DecimalFormat HALF_UP舍入错误

时间:2017-07-14 07:12:07

标签: java rounding bigdecimal

我使用带有HALF_UP舍入模式的DecimalFormat,我有一个不能正常工作的escenery,我不知道为什么。

DecimalFormat df = new DecimalFormat("#.##");
df.setRoundingMode(RoundingMode.HALF_UP);
float tmp = (float) (0.5 * 1.05);
df.format(tmp);
float mul = Float.parseFloat(df.format(tmp));

mul变量值我希望有0.53值,我收到0.52值。

我正在使用Java 1.8.0_131。

已解决的最终法典

BigDecimal mul = new BigDecimal(0.5).multiply(new igDecimal(1.05));
mul = mul.setScale(2, RoundingMode.HALF_UP);
System.out.println(mul);

1 个答案:

答案 0 :(得分:8)

您使用的是float数据类型。

此数据类型无法精确保存值0.525。请参阅此代码以明确说明:

float value = (float) (0.5 * 1.05);
DecimalFormat df = new DecimalFormat("#.########################");
System.out.println(df.format(value));

打印出来:

  

0.5249999761581421

使用模式RoundingMode.HALF_UP舍入此值将正确产生0.52

double似乎能够精确存储值0.525

double value = 0.5 * 1.05;
DecimalFormat df = new DecimalFormat("#.########################");
System.out.println(df.format(value));

这将打印预期值:

  

0.525

使用模式RoundingMode.HALF_UP舍入该值现在将产生0.53

警告:即使double数据类型也不能精确存储值!

看看@MarkDickinson的评论。存储的值为0.52500000000000002220446049250313080847263336181640625,恰好大于0.525,并且只是意外舍入到预期值。

那该怎么办?

数据类型floatdouble是基于二进制的,而我们人类在处理数字时倾向于认为基于十进制。阅读文章"What Every Computer Scientist Should Know About Floating-Point Arithmetic"了解更多信息。

解决方案是使用基于十进制的数据类型,该类型存在于BigDecimal