我正在将DecimalFormat与HALF_UP舍入模式一起使用,并且有一个无法正常工作的提示,并且我不知道为什么。

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);

最佳答案

您正在使用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中存在的基于十进制的数据类型。

07-24 09:19