奇怪的Double运算

今天测试同学反馈有一个运行了很久的程序,最近的崩溃率很高,通过日志查询发现,这是一个查询进度的接口,进度结果的精度是小数点后两位。

但是日志中却有很多的超过这个精度的结果,简化了一下代码:

1 double progress = 0.07000000000001D;
2 DecimalFormat df = new DecimalFormat("0.00");
3 String value = df.format(progress);
4 if (progress > 0 && progress <= 1) {
5      double progressResult = Double.parseDouble(value);
6      progressResult = progressResult * 100;
7 }

这里首先是将progress的精度转换为小数点后两位,然后再进行乘以100 ,目的是为了转换成100%的结果,但是执行起来结果却和我们预期的不一样。

这里我们通过断点的方式可以看到,转换完之后的progressResult竟然又恢复到了原来的精度。

 

这是因为在计算机的内部是通过二进制码来进行计算的,我们看到的double的值可能是0.1,但是实际情况可能是0.100000000000000001,因为要展示这个数字是需要再从二进制数转回成十进制的,所以后面的内容就无法正确的显示。但是仍然是真是存在的。所以我们虽然前面已经通过Format的方式将progress的精度调整了,但是后面的位数还是存在的,所以在乘以100之后,结果就变成了现在的结果。所以在程序中,如果有double或者是float的值进行计算的,一定要使用BigDecimal来进行正确的处理。

 

下面是正确的处理方式:

1 double progress = 0.07000000000001D;
2 DecimalFormat df = new DecimalFormat("0.00");
3 String value = df.format(progress);
4 if (progress > 0 && progress <= 1) {
5     BigDecimal valueResult = new BigDecimal(value);
6     double progressResult = valueResult.multiply(new BigDecimal(100)).doubleValue();
7 }

 

posted @ 2019-10-31 21:09  SyrupzZ  阅读(140)  评论(0编辑  收藏  举报