解决方案 »

  1.   

    摘自:http://blog.csdn.net/bingjing12345/article/details/7907095对 double 不能算出精确值问题的思考
    我知道 double型数据在内存的表示遵循IEEE标准,对于0.1  ,1.1,2.1等等 很多数,不能被精确的表示为double数据
    只能被表示为最接近它的double值
    先来看一段程序
    double d1 = 0.9;
    double d2 = 0.1;
    double d3 = 1.1;
    System.out.println(d1);
    System.out.println(d2);
    System.out.println(d3);
    输出为:
    0.9
    0.1
    1.1输出结果  并没有 变成我们想象的那种 0.99999999999999 或者1.10000000000000001
    这说明0.1, 1.1 本身就是double型最接近它们的值。
    再来看一段:
    System.out.println(5.0 - 4.1);
    System.out.println(5.0 - 3.1);
    System.out.println(5.0 - 2.1);
    System.out.println(5.0 - 1.1);
    System.out.println(5.0 - 0.1);
    System.out.println("******************");
    System.out.println(4.0 - 3.1);
    System.out.println(3.0 - 2.1);
    System.out.println(2.0 - 1.1);
    System.out.println(1.0 - 0.1);
    System.out.println("******************");
    System.out.println(4.0 - 0.1);
    System.out.println(3.0 - 0.1);
    System.out.println(2.0 - 0.1);
    System.out.println(1.0 - 0.1);输出结果:
    0.9000000000000004
    1.9
    2.9
    3.9
    4.9
    ******************
    0.8999999999999999
    0.8999999999999999
    0.8999999999999999
    0.9
    ******************
    3.9
    2.9
    1.9
    0.9
    这些结果开始时超出了我的想象
    从第一组数据看,相差大于1的,好像结果是对的,
    从第二组看,相差小于1的,结果居然也有对的,
    从第三组看,和0.1作差的全是对的。那么  0.1跟1.1,2.1等等其它数有什么不同呢? 相差大于1的时候结果怎么就变对了呢?
    问题就出现在0.1 的IEEE表示上,
    因为它标准化的时候0.1要小数点被向右移位,而其它数 小数点像左移
    这样0.1算的实际位数要比 2.1,3.1等等 其它数多几位, 即0.1本身的double型表示比2.1中的那个0.1要精确。在做double型减法运算时,需要经过对阶,求和,右规,舍入(0舍1入)操作
    如5.0-0.1 对阶需要移动5位,计算舍入后最后得出4.9。这个4.9中的0.9其实是一个不精确的数,但0.9比0.8999999999999或者0.90000000001更接近真实值。
    而5.0-4.1对阶时 不需要移动,计算舍入后最后得出0.9000000000000004, 这个数也不是一个精确值,只是因为真实值相对于0.9000000000000003或者0.9000000000000005,跟接近与0.9000000000000004.假如我的想法正确,那么就是对阶移动位数比较多时,计算机能得出跟数学计算一样的值,否则得出一个其他值。
    验证
    System.out.println(100.0 - 0.1);
    System.out.println(100.0 - 99.1);
    99.9
    0.9000000000000057
    综上,结论是对的。
     
    同样的道理,假如 某个数a 大于2^54;  因为double型的尾数是52位, 加上标准化的一位 共53位,
    那么将a转换为double型时,采用恒掉的方法,只能取前53位, 又假如 a的第54位为0,  则(double)a+1 = = (double)a