整数和浮点数在Java虚拟机中的表示

433 阅读3分钟

本文是《实战Java虚拟机——JVM故障诊断与性能优化》的读书笔记

1.整数在JVM中的表示

整数在JVM中使用补码表示,什么是原码、补码、反码?

原码: 符号位+二进制值,符号位在最左边,如:

 10的原码:  00000000 00000000 00000000 00001010 // 最左边的0表示正数
-10的原码:  10000000 00000000 00000000 00001010 // 最左边的1表示负数

反码: 符号位不变,其它位取反,如:

 10的反码:  01111111 11111111 11111111 11110101 // 最左边的0表示正数
-10的反码:  11111111 11111111 11111111 11110101 // 最左边的1表示负数

补码: 正整数和负整数的补码不一样,正整数的补码就是原码本身,负整数的补码就是反码加一。如:

////// 正整数的补码 = 原码
 10的补码:  00000000 00000000 00000000 00001010

////// 负整数的补码 = 反码 + 1

  10000000 00000000 00000000 00001010  // -10原码
  11111111 11111111 11111111 11110101  // -10反码
+                                   1  // +1
--------------------------------------------------
  11111111 11111111 11111111 11110110  // 结果:-10的补码

2.浮点数在JVM中的表示

Java中的浮点数有float和double两种类型,float占32位,double占64位。下面以float来说明。

float的32位分成三个部分来表示一个浮点数:

     s               eeeeeeee           mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
     |                   |                                |
  符号位(1)           指数位(8)                        尾数位(23)

浮点数取值公式是:sflag * m * 2^{(e-127)}

其中,当符号位s=0时,表示公式中slag=1,即正数;s=1时,slag=-1,即负数。如下:

s=0 --> m * 2^{(e-127)}

s=1 --> -m * 2^{(e-127)}

另外,公式中m的值,根据e的值会动态变化。 当8个指数位e全部为0,尾数位m附加0,否则,附加1。

举例说明,-5的表示为:

1     1000 0001       010 0000 00000000 00000000
|          |
sflag=-1   |
           |
           e=129

尾数位原来是010 0000 00000000 00000000,但是指数位1000 0001不全为0,所以尾数位(从左边)附加1,(不能当做算法的加1,当做字符串的拼接那样子理解好点)变成这样子:

1 + 010 0000 00000000 00000000 = 1010 0000 00000000 00000000

套公式计算:sflag * m * 2^{(e-127)}

计算过程:

  • sflag = -1

  • 2^{(e-127)} = 2^{(129-127)} = 2^{(2)} = 4

  • m的计算复杂点,尾数位表示2的指数次方的和。计算过程:1*2^{0} + 0*2^{-1} + 1*2^{-2} + 0*2^{-3}......= 1 + 0 + \frac{1}{2^{2}} + 0 = 1 + 0.25 = 1.25

所以:

sflag * m * 2^{(e-127)} = -1 * 1.25 * 4 = -5

浮点数的表示有点复杂。看过了解一下就好啦。