如何理解IEEE 754标准对Java中float值和double值的规定

Posted chang4

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何理解IEEE 754标准对Java中float值和double值的规定相关的知识,希望对你有一定的参考价值。

在Java语言中,我们可以使用float和double这两种基本数据类型来表示特定的数据。

这两种数据类型,本质上是浮点数(floating-point number),浮点是一种对于实数的近似值数值表现法,由一个有效数字加上幂数来表示。

之所以使用浮点数,是因为计算机在使用二进制运算的过程中,无法将所有的十进制小数准确的换算为二进制,只能使用近似值来表示。

使用浮点数表示数值的方法很多,在Java中,和C语言一样,float和double都采用了使用最为广泛的IEEE 754标准。

IEEE 754标准的全称为IEEE二进制浮点数算术标准(ANSI/IEEE Std 754-1985),其中ANSI是美国国家标准学会(American National Standards Institute)的缩写,IEEE是电器电子工程师学会(Institute of Electrical and Electronics Engineers)的缩写,754是该标准的编号,1985则是该标准发布的年份。

 IEEE 754规定,一个二进制浮点数在存储中由三部分组成:

技术分享图片

 其中第一部分为符号位(sign bit),第二部分为指数偏移值(exponent bias)用于存储浮点数的指数部分,第三部分为分数(fraction)用于存储浮点数的有效数的小数部分。

以一个具体的float值为例,Java中的float值采用的是IEEE754中的单精度标准,使用32个比特进行存储。例如:

0100 0100 1010 0110 1001 1110 0000 0000

其中:

0100 0100 1010 0110 1001 1110 0111 0100

第一位的0为符号位,它表示这个数的正负值为正,相应的,若第一位为1则表示这是一个负数;

0100 0100 1010 0110 1001 1110 0000 0000

第2~9的8个比特存储的是指数偏移值,用于记录该float值的指数部分,取值范围为-126~+127再加上偏移值127(2的7次方减1),结果就是1~254(0和255留作特殊值)。在本例中,1000 1001在十进制中的值为137,但是137是进行偏移后的结果,减去偏移值127后,其实际代表的指数值就是10。

0100 0100 1010 0110 1001 1110 0000 0000

第10~32的23个比特存储的是该float值的分数/小数部分。010 0110 1001 1110 0000 0000实际上表示的就是二进制的0.010 0110 1001 1110 0000 0000再加上1,也就是1.010 0110 1001 111。这实际上就是二进制的1010 0110 1001 111右移十四位的结果。1010 0110 1001 111在十进制中的值为21327,所以1.010 0110 1001 111也就等于21327*2^(-14)。

综上,例子中的:

0100 0100 1010 0110 1001 1110 0000 0000

实际上也就等于:

            +        21327*2^(-14)   *   2^10    =  1332.9375

第一位符号位表示        第10~32的分数位表示  第2~9的指数位表示

 

反之,例如我们想知道某个float a = 1000在内存中的形式,那么则需要如下操作:

首先,1000是个整数,所以第一个比特位存储的是0。

十进制的100在二进制中为11 1110 1000,这实际上就是1.111101左移9位的结果,
那么实际上指数位存储的结果就应该是9 + 127 = 136也就是1000 1000

分数位存储的则是1.111101减去1的部分,补齐23位,也就是111 1010 0000 0000 0000 0000

综上float a = 1000在内存中的存储为:

0100 0100 0111 1010 0000 0000 0000 0000

 

 

另外,前面提到过的,指数偏移值为0或255的时候代表特殊值:

当指数值为0,即0000 0000时,若小数部分为0,则这个数为±0(正负由符号位决定);

当指数值为255,即1111 1111时,若小数部分为零,则这个数为±∞(正负由符号位决定);

当指数值为255,即1111 1111时,若小数部分非零,则这个数表示为不是一个数(Not a Number)。

 

以上就是float的部分,double同理,只不过double采用IEEE 754双精度标准,使用64个比特存储,其中2~12的11位为指数位,13~64的52位为小数位。

 

References:

IEEE 754 - wiki
https://zh.wikipedia.org/zh-cn/IEEE_754

浮点数 - wiki
https://zh.wikipedia.org/zh-cn/%E6%B5%AE%E7%82%B9%E6%95%B0





以上是关于如何理解IEEE 754标准对Java中float值和double值的规定的主要内容,如果未能解决你的问题,请参考以下文章

IEEE 754标准

Java中浮点类型的精度问题 double float

ieee754单精度浮点数 表示方法

IEEE754标准以及非常规划定义,double的二进制转换工具类

IEEE 754标准如何转换?

由IEEE 754深入理解浮点数