![实战Java虚拟机:JVM故障诊断与性能优化(第2版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/901/47378901/b_47378901.jpg)
1.5.2 浮点数在Java虚拟机中的表示
在Java虚拟机中,浮点数有float和double两种,分别是32位和64位浮点数。浮点数在虚拟机中的表示比整数略显复杂。目前,使用最为广泛的是由IEEE 754定义的浮点数格式。目前Java虚拟机中对于浮点数的处理参考IEEE 754的规范。本节将以float为例,简要介绍浮点数的表示方法。
在IEEE 754的定义中,一个浮点数由3部分组成,分别是符号位、指数位和尾数位。以32位float类型为例,符号位占1位,表示正负数,指数位占8位,尾数位占剩余的23位,如图1.2所示。
其中,sflag表示符号,当s为0时,sflag为1,当s为1时,sflag为-1。m为尾数值,实际占用空间为23位,但是根据e的取值,有24位精度。当e全为0时,尾数位附加为0,否则,尾数位附加为1。e为指数位,用8位表示。
![](https://epubservercos.yuewen.com/8F60EA/26763631609316106/epubprivate/OEBPS/Images/31_1.jpg?sign=1739210286-1CaHpmLgD7fp5w9lp4mKcs1lMxfLWbUQ-0-1ef0ceff7f6276cdebad979f6d43f4de)
图1.2 浮点数格式
以浮点数-5为例,其内部表示为:
1 10000001 01000000000000000000000
符号位为1表示负数,指数位为10000001,表示129。
尾数位为:01000000000000000000000。因为e不全为0,故实际的尾数位为:
101000000000000000000000
尾数位表示2的指数次幂的和,每一位表示求和数列中的对应项是否为0,这里表示:
1*20+0*2-1+1*2-2+0*2-3+0*2-4+0*2-5+…,对应关系如图1.3所示。
![](https://epubservercos.yuewen.com/8F60EA/26763631609316106/epubprivate/OEBPS/Images/31_2.jpg?sign=1739210286-f7zXxnrwmoDftcqxMdKZFWCUj2BYmnwm-0-f9f5671c2551de225791c7869eaa5ece)
图1.3 尾数的计算
故1 10000001 01000000000000000000000的值为:
-1*2(129-127)*(1*20+0*2-1+1*2-2+0*2-3+0*2-4+0*2-5)=-1*4*1.25=-5
float浮点数还可以表示一些特殊的数字,如表1.1所示。
表1.1 float的特殊数字
![](https://epubservercos.yuewen.com/8F60EA/26763631609316106/epubprivate/OEBPS/Images/32_1.jpg?sign=1739210286-2Sigu7kAVxZnpj4uwe9lkZGPVGngge7J-0-5fbb63ded660f8a60805bd0a9f8c0262)
其中,指数位全为1表示无穷大和NaN等特殊数字。指数位全为0为非规范化的浮点数。
【示例1-2】在Java中,使用Float.floatToRawIntBits()函数可以获得一个单精度浮点数的IEEE 754表示。以下代码打印了-5的内部表示:
![](https://epubservercos.yuewen.com/8F60EA/26763631609316106/epubprivate/OEBPS/Images/32_2.jpg?sign=1739210286-ap3iqYCBmGBBRqMmtRN0bAcJh5HXah0D-0-77efb728e98a2611a2d9f07e95a245b3)
程序运行结果为:
![](https://epubservercos.yuewen.com/8F60EA/26763631609316106/epubprivate/OEBPS/Images/32_3.jpg?sign=1739210286-kwb5yZwKQWRwptb32EyAYqa9dAaZfpOz-0-e1eed8e9cd1972a486e7ab464247b03f)
其中,Float.floatToRawIntBits()函数最终由native方法实现,具体实现如下:
![](https://epubservercos.yuewen.com/8F60EA/26763631609316106/epubprivate/OEBPS/Images/32_4.jpg?sign=1739210286-KojrPvXRmioR0WjCcWeA7R1yqp5JO4Xj-0-bd11a7666e6e9e1d2ac71e73dea70c8b)
从上述代码可以看出,为了获取float的内部表示,使用了C语言中的union自然实现这个转换。