日期:2014-05-20  浏览次数:20627 次

精度问题讨论
当作散分吧

今天一直在想这个问题
不明白问什么会有奇怪的结果
找了书,查了资料
深入理解计算机系统都搬出来看了
想了很多道理都不能解释的通

                System.out.println(1.20-1.10);
                System.out.println(1.30-1.10);
                System.out.println(1.40-1.10);
                System.out.println(1.50-1.10);
                System.out.println(1.60-1.10);
                System.out.println(1.70-1.10);
                System.out.println(1.80-1.10);
                System.out.println(1.90-1.10);
                System.out.println(2.00-1.10);
                System.out.println(2.10-1.10);

打印结果:
0.09999999999999987
0.19999999999999996
0.2999999999999998
0.3999999999999999
0.5
0.5999999999999999
0.7
0.7999999999999998
0.8999999999999999
1.0

按照官方解释是说1.10这个数字不能被精确表示成为一个double,因此它被表示成为最接近它的double值(从而会造成一堆数字)

我接受了,但是大家可以看到上面的结果是0.5,0.7和1.0都还是很好的结果
而且我在想其实像1.10这样的数字实在是太多了,从统计上来讲有一大半都是不能被有限二进制表示的,难道这些都要造成这么复杂的结果?

关键是这里打印出来了0.5,0.7和1.0
经过实验,人为造出了这些数字的有一串的形式,列举如下:
                System.out.println(2.20-1.70);
                System.out.println(2.20-1.50);
                System.out.println(2.20-1.20);
                System.out.println(1.0000000000000003);

打印结果如下:
0.5000000000000002
0.7000000000000002
1.0000000000000002
1.0000000000000002

从而消除了0.5,0.7和1.0是因为可以被有限表示而有很好结果的可能
(最后一个是该数的最近表示,作为参考)

我暂时的问题就在这里了
假如说是1.10的问题,为什么0.5,0.7和1.0却能够出现?

欢迎大家讨论~~

------解决方案--------------------
好简单,因为数在计算机内部表示为二进制数,这点lz的深入理解计算机系统应该有说明。
二进制转换成十进制很多时候是不能精确转换的,
当然也有例外,如1.60-1.10=0.5.
但为何2.20-1.70!=0.5呢?那大概是2.2或者1.7转化成二进制时失去了精度所导致的

------解决方案--------------------
帮顶一下
------解决方案--------------------
帮顶
------解决方案--------------------

------解决方案--------------------
看3楼的回复。
------解决方案--------------------
我来说两句~
首先是:2.20 - 1.70
把2.20转成2进制:
0 10000000000 0001100110011001100110011001100110011001100110011010
2进制科学记数法表示:
1.0001100110011001100110011001100110011001100110011010 * 2的1次幂
(指数位是10000000000,因为有127的偏移量,所以就是1次幂)

1.70的2进制
0 01111111111 1011001100110011001100110011001100110011001100110011
2进制科学记数法表示:
1.1011001100110011001100110011001100110011001100110011 * 2的0次幂

做减法时先把幂次对齐
10.0011001100110011001100110011001100110011001100110100
1.1011001100110011001100110011001100110011001100110011
-------------------------------------------------------
0.1000000000000000000000000000000000000000000000000001
换下写法:
1.0000000000000000000000000000000000000000000000000010 * 2的-1次幂
就是:
0 01111111110 0000000000000000000000000000000000000000000000000010