Java DecimalFormat HALF_UP 舍入错误
Java DecimalFormat HALF_UP rounding error
我正在使用带 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);
您正在使用 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
并且只是意外地四舍五入到预期值。
那怎么办?
数据类型float
和double
是基于二进制的,而我们人类在处理数字时倾向于认为是基于十进制的。阅读文章 "What Every Computer Scientist Should Know About Floating-Point Arithmetic" 了解更多信息。
解决方案是使用基于小数的数据类型,它存在于 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);
您正在使用 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
并且只是意外地四舍五入到预期值。
那怎么办?
数据类型float
和double
是基于二进制的,而我们人类在处理数字时倾向于认为是基于十进制的。阅读文章 "What Every Computer Scientist Should Know About Floating-Point Arithmetic" 了解更多信息。
解决方案是使用基于小数的数据类型,它存在于 BigDecimal
。