[英]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. float
和double
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.