2017-07-14 160 views
0

我正在使用带有HALF_UP舍入模式的DecimalFormat,并且我有一个escenery,其中的工作不正常,我不知道为什么。Java 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); 
+0

Thank you for your comment,but I round rounding as HALF_UP must works“Rounding mode to round to”nearest neighbor“,除非两个邻居是等距离的,在这种情况下,四舍五入。“[Oracle Documentation](https://docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html) –

+2

'float'和'double'无法精确地存储值...请参阅:https ://stackoverflow.com/q/3413448/4899193 –

+0

This works' System.out.println(df.format(0.5 * 1.05));' - 当然双打 –

回答

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中。

+0

这个答案是有误导性的,'double'不能精确地存储'0.525'的值:它存储的是'0.52500000000000002220446049250313080847263336181640625',因为这个值只是_happens_高于'0.525',它向上舍入。 0.7 * 1.05',你会发现它是舍入而不是up.OP如果正确舍入_decimal_ halfway的情况下,他们需要使用一个十进制基于数字的类型。 –

+0

谢谢您的快速回复,但我的四舍五入继续发生错误: 'double tmp = 0.5 * 1.05; DecimalFormat df = new DecimalFormat(“#。##”); df.setRoundingMode(RoundingMode.HALF_UP); System.out.println(df.format(tmp));' Thats returns 1.52 –

+0

@MarkDickinson感谢您的发现。我不知何故错过了它。改变了我的答案。 – Seelenvirtuose