java 浮点数表示法

这个要从Double类的一个方法说起:Double.doubleToLongBits(double value),根据官方文档,其部分注释内容如下:

public static long doubleToLongBits(double value)
Returns a representation of the specified floating-point value according to the IEEE 754 floating-point "double format" bit layout.

Bit 63 (the bit that is selected by the mask 0x8000000000000000L) represents the sign of the floating-point number. Bits 62-52 (the bits that are selected by the mask 0x7ff0000000000000L) represent the exponent. Bits 51-0 (the bits that are selected by the mask 0x000fffffffffffffL) represent the significand (sometimes called the mantissa) of the floating-point number.

个人翻译一下:

根据IEEE 754浮点“double格式” 比特位的布局,返回一个浮点值。

bit63表示符号位,bits62-52表示指数域,bits51-0表示有效数字(尾数域)

关于 IEEE 754,可以参考该博客:https://blog.csdn.net/m0_37972557/article/details/84594879

现在做如下测试:

System.out.println(Double.doubleToLongBits(0.75));

System.out.println(Double.doubleToLongBits(0.5));

结果

0.75

十进制值:4604930618986332160

十六进制值:3FE8 0000 0000 0000

0.5

十进制值:4602678819172646912

十六进制值:3FE0 0000 0000 0000

对于0.75的十六进制,其符号位为0,指数域为3FE,尾数域为 8 0000 0000 0000

计算过程:

  指数域0x3FE的十进制为:1022,而指数域的偏移码是:1023,因此实际的指数值为:1022 -1023 = -1

  对于尾数域,后面的一堆0不看,最左边的值就是1,则表示其有效值为0.1,而尾数域的正规表示形式为:1.xxx(最左边的1在转换为浮点表示时会自动省略),因此尾数的实际值的计算方法是其有效值加1,即:1 + 0.1 = 1.1,该结果是二进制值

  通过上面两步,拿到了指数为-1, 位数为1.1(二进制)

  结果计算3种方法,结果一致,都是0.75

    小数点移位法:指数域为-1,表示尾数1.1的小数点往左移动一位,得出结果: 0.11,转换成十进制就是:0.5 + 0.25 = 0.75

    二进制相乘:指数域为-1,表示实际的指数结果为:2-1,即0.5,二进制表示为0.1,计算:1.1 * 0.1 = 0.11,十进制即0.75

    十进制相乘:指数域为-1,表示实际的指数结果为:2-1,即0.5,而1.1的十进制表示为1.5,计算:1.5 * 0.5 = 0.75

同理:

  0.5的十六进制中的有效数值3FE0,算出来指数域是-1,尾数域是0,结果为:0.1,转为十进制:0.5

可以类推:

  0.25的浮点表示为:0x3FD0 0000 0000 0000

  -0.25的浮点表示为:0xBFD0 0000 0000 0000

  0.625的浮点表示为:0x3FE4 0000 0000 0000

  1.5的浮点表示为:0x3FF8 0000 0000 0000

  -3.625的浮点表示为:0xC00D 0000 0000 0000

 

除了最开始提到的方法外,Double类还提供一个逆过程的方法如下,可以传入浮点表示法的值(8个字节,所以要用long类型接收),然后返回实际的double值

public static native double longBitsToDouble(long bits);

这居然是一个native方法,不知道是C++支持还是操作系统支持的这个方法。

因为双精度浮点表示的指数最大值是1023,因此其可表示的最大值为:21023 * 0x1.FFFFFFFFFFFFF(13个F),约等于:1.7976931348623157e+308

在jdk1.8的源码中,其表示如下:

public static final double MAX_VALUE = 0x1.fffffffffffffP+1023;

猜你喜欢

转载自www.cnblogs.com/zhangxuezhi/p/12036700.html