全部博文(69)
分类: Java
2012-04-12 23:54:12
前几天同事在群里提到这样的一个问题:
System.err.println(Integer.toBinaryString(Float.floatToIntBits(1.6777215E7F)));
System.err.println(Integer.toBinaryString(Float.floatToIntBits(1.36E-43F)));
一个输出是32位,一个才7位
输出结果:
1001011011111111111111111111111
1100001
这个函数是想打印出1.36E-43F的二进制格式,在java里float类型是占32位的,但是这里只输出了7位,这是为什么呢?
1)首先,我们得了解float类型在java里的表示方式
java里的float是按照 IEEE 754 单精度浮点型的格式存储的,格式为:
(-1)^s*1.M*2^e
s代表符号位,如果该数为正数,则s=0;若为负数,则s=1
1.M中,M代表尾数,默认前面隐含一个1
e代表指数,存储的时候用的是移码
首先,将十进制的浮点数转为(s)1.M*2^e的格式,
然后依次将s,M和e+127分别存储到第31位,第23~30位,第0~22位上去
如下所示:
31 | 30~23 | 22~0 |
s(符号位,正数为0,负数为1) | e+127(指数移码) | m(尾数) |
说的不是很清楚,就拿上面的第一个数举例:
1.6777215E7F
=16777215D 转成十进制
=1111111111111111111111111B 转成二进制
=(0) 1.1111111111111111111111*2^23 转成IEEE754支持的格式
那么这个数的符号位为1,e为23,尾数m为111111111111111111111111
其中,e要用移码进行表示e+127=150D=10010110B
那么,最终这个浮点数在内存中的表示形式为:
0 10010110 1111111111111111111111
floatToIntBits方法调用floatToRawIntBits方法,floatToRawIntBit是一个native方法,该方法取得1.6777215E7F的IEEE 745格式,即是
0 10010110 1111111111111111111111,
3)最后对比一下结果0 10010110 1111111111111111111111 和
1001011011111111111111111111111,貌似有点不一样,只是少了前面的一个零,这是因为Integer.toBinaryString这个方法里会从第一个不为零的位开始打印,所以少了一位,同理1.36E-43F的输出其实应该为0000000000000000000000001100001,前导的零都忽略掉了,所以只有7位。