- 实战Java虚拟机:JVM故障诊断与性能优化(第2版)
- 葛一鸣
- 627字
- 2025-02-25 19:41:12
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位表示。

图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所示。

图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的特殊数字

其中,指数位全为1表示无穷大和NaN等特殊数字。指数位全为0为非规范化的浮点数。
【示例1-2】在Java中,使用Float.floatToRawIntBits()函数可以获得一个单精度浮点数的IEEE 754表示。以下代码打印了-5的内部表示:

程序运行结果为:

其中,Float.floatToRawIntBits()函数最终由native方法实现,具体实现如下:

从上述代码可以看出,为了获取float的内部表示,使用了C语言中的union自然实现这个转换。