int i = Integer.MAX_VALUE;//2147483647  float f = 2.1474836E9f;//单步跟踪下, f 的值是 2.14748365E9
 
int j = (int)f; boolean bi = i == j;
System.out.println("bi=  "+bi);上面这段代码执行后,bi将等于 true,是什么原因呢? 单步跟踪下, f 的值是 2.14748365E9,明显与程序中不一样。搜索了一下,也没找到有关float 和double在java中存储的清楚详细的说明。谁有这个的详细说明?(最好画个图)

解决方案 »

  1.   

    这个涉及到浮点数的结构(符号位,指数部分,尾数部分),以及规格化的表示和非规格化的表示。
    这里不详细解释,LZ可查阅相关资料
    有几个知识点:
      1.计算机中浮点数的基数是2.
      2.指数部分有偏移量(float为127, double为1023)
      3.规格化的表示小数点左边一定为1.(二进制数)
      4.float类型 符号位占1位,指数部分占8位,尾数占23位(因为规格化表示,小数点左边一定为1,所以实际有24位精度)
      5.double类型 符号位占1位,指数部分占11位,尾数占52位(因为规格化表示,小数点左边一定为1,所以实际有53位精度)看一个例子float 0.6吧:
    第一步,把十进制转2进制:
     0.6的二进制表示(乘2取整,顺序表示):
       .1001 1001 1001 1001 1001 1001 1001 ... 无限循环下去。第二步,计算尾数部分:
     把.1001 1001 1001 1001 1001 1001 1001 ...规格化表示(小数点移到第一个非0书右边)就是:
       1.001 1001 1001 1001 1001 1001 1001 ...,右移了1位。
     由于规格化表示的数小数点左边一定为1,把这个1舍弃,并保留float尾数能表示的23位,最终尾数部分是:
       001 1001 1001 1001 1001 1001第三步,计算指数部分: 
     由于计算尾数时右移了1位,相当于乘以2的负1次,所以指数为-1,加上float偏移量127,最后指数为126,
     二进制表示为 0111 1110第四步,符号部分:
     0.6为正数,符号位为0最终0.6在计算机中的表示就是: 符号位    指数              尾数
       0    0111 1110  001 1001 1001 1001 1001 1001
    --------------------------------------------------------------
    我们再从这个2进制来计算10进制数:(2的指数次 * 尾数)
     符号位0--> 为正
     指数 0111 1110:为126, 减去偏移量127,结果为-1.
     尾数 001 1001 1001 1001 1001 1001: 规格化的时候小数点左边人掉了一个1,现在加上:
        1.001 1001 1001 1001 1001 1001,转为10进制就是:
        1*2^0 + 1*2^-3 + 1*2^-4 + .....= 1.19999992847442626953125
    1.19999992847442626953125 * 2^-1 = 0.599999964237213134765625
    所以最终结果是一个无限接近于0.6而不能精确表示0.6
      

  2.   

    http://hi.baidu.com/yu_xiyan/blog/item/1eec739575c36241d0135e0f.html
    结贴,散分