IEEE 754标准
在C/C++等编程语言中,浮点数在计算机中的表示采用的是IEEE 754标准。该标准一共的规定了四种表示浮点数值的方式,其中常见的表示方式有两种:单精确度(32位)和双精确度(64位)。这两种表示方式在C/C++语言中分别可以用float和double关键字来定义。
单精度浮点数的表示方法
单精度浮点数的表示方法其实就是把一个32位分成了三个部分:
- 第一个部分,占1位,表示浮点数的符号,英文Sign,简称为S。
- 第二个部分,占8位,表示浮点数的指数,英文Exponent,简称为E。
- 第三个部分,占23位,表示浮点数的尾数,英文Mantissa,简称为M。
如下图所示:
31 22 0
+----------------------------------+
|S|EEEEEEEE|MMMMMMMMMMMMMMMMMMMMMMM|
+----------------------------------+
30 23
对应浮点数表示的值为:
结合上面的公式,来理解各个部分的意义就更容易了:
-
符号部分,
当S为0时,,表示浮点数的值大于0;同理,当S为1时,,表示浮点数的值小于0。
-
指数部分,
首先要明白:对于任何一个正实数x,都可以找到一个整数n,使得。举个例子,比如5,可以找到n=2,使得,即。浮点数中的指数部分就是这里的n。
那么为什么还要减去127呢?因为当浮点数值的绝对值小于1时,指数部分其实是小于0的。举个例子,比如0.45,只有时,使得,即。而浮点数中指数部分占8位,可以表示范围[0-),即[0-256),为了在指数部分能够表示负数,
IEEE 754规定减去127,即。所以,如果浮点数的,那么实际的E应该是125。 -
尾数部分,
尾数部分占23位,可以表示范围[0-),即[0-8388608)。
可以这样理解尾数部分:把一条线分成8388608个段,也就是把到分成8388608个线段。尾数部分的值M,表示从到浮点数值的绝对值x所要经过的线段数量,也就是到x的长度占到长度的比例是多少。这个比例的值就是尾数部分公式中的来由,而加1则表示线段的起点的值。
单精度浮点数举例
有了上面的说明,再结合例子来理解一下,比如浮点数3.14:
-
符号部分
因为3.14大于0,所以。
-
指数部分
,所以,那么。
-
尾数部分
到3.14的长度占到长度的比例是
总线段数量为,那么,从到3.14所要经过的线段数量,四舍五入,转换成整数结果为。因为有四舍五入,所以浮点数保存的数据和实际数据是有误差的。
把S、E、M转换成二进制,就可以得到3.14的二进制表示0x4048f5c3:
S E M
+----------------------------------+
|0|10000000|10010001111010111000011|
+----------------------------------+
最后代入浮点数公式计算:
也可以使用IEEE-754浮点数转换工具来分析浮点数的表示方法。
双精度浮点数的表示方法
双精度浮点数和单精度浮点数的原理是一样的,只是各个部分长度不同而已。
双精度浮点数的表示方法其实就是把一个64位分成了三个部分:
- 第一个部分,占1位,表示浮点数的符号,英文Sign,简称为S。
- 第二个部分,占11位,表示浮点数的指数,英文Exponent,简称为E。
- 第三个部分,占52位,表示浮点数的尾数,英文Mantissa,简称为M。
对应浮点数表示的值为: