简体   繁体   English

Java DecimalFormat HALF_UP舍入错误

[英]Java DecimalFormat HALF_UP rounding error

I'm using the DecimalFormat with HALF_UP rounding mode and I have an escenery where is not working correctly and I don't know why. 我使用的是带有HALF_UP舍入模式的DecimalFormat,并且存在一个无法正常工作的提示,并且我不知道为什么。

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

The mul variable value I hope have 0.53 value and I received 0.52 value. 我希望mul变量值为0.53,而我收到的值为0.52。

I'm using the Java 1.8.0_131. 我正在使用Java 1.8.0_131。

SOLVED FINAL CODE 解决的最终代码

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

You are using the float datatype. 您正在使用float数据类型。

This datatype is not able to precisely hold the value 0.525 . 此数据类型不能精确地保存值0.525 See this code for making it clear: 请参阅以下代码以使其清楚:

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

This prints out: 打印输出:

0.5249999761581421 0.5249999761581421

Rounding such a value with the mode RoundingMode.HALF_UP will correctly yield 0.52 . 使用RoundingMode.HALF_UP模式RoundingMode.HALF_UP该值将正确产生0.52

The double value seems to be able to precisely store the value 0.525 : double似乎可以精确存储值0.525

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

This will print the expected value: 这将打印期望值:

0.525 0.525

Rounding that value with the mode RoundingMode.HALF_UP will now yield 0.53 ! 使用RoundingMode.HALF_UP模式RoundingMode.HALF_UP入该值现在将产生0.53

Caution: Even the double datatype does not store the value precisely! 注意:即使double数据类型也不能精确存储值!

Look at @MarkDickinson's comment. 看看@MarkDickinson的评论。 The stored value is 0.52500000000000002220446049250313080847263336181640625 which happens to be larger than 0.525 and only rounds by accident to the expected value. 存储的值是0.52500000000000002220446049250313080847263336181640625 ,该值恰好大于0.525并且偶然地0.52500000000000002220446049250313080847263336181640625入到期望值。

So what to do? 那么该怎么办?

The data types float and double are binary-based, whereas we humans tend to think decimal-based when dealing with numbers. floatdouble float数据类型是基于二进制的,而我们人类在处理数字时往往会认为基于十进制。 Read the article "What Every Computer Scientist Should Know About Floating-Point Arithmetic" for much more information. 有关更多信息,请阅读文章“每个计算机科学家应该对浮点算法了解什么”

The solution is to use a decimal-based data type, which exists in BigDecimal . 解决方案是使用存在于BigDecimal的基于十进制的数据类型。

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

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