IEEE二进制浮点数算术标准(IEEE 754)。IEEE 754 定义了表示浮点数的格式、反常值、特殊数值、浮点数运算,以及四种数值舍入规则和五种例外状况。
浮点数的二进制表示方式
IEEE 754规定了四种表示浮点数值的方式:单精度(32bit)、双精度(64bit)、延伸单精度(>43bit)和延伸双精度(>79bit)。以下以单精度为例说明。
存储格式
IEEE 754 规定的二进制浮点数分为三部分,由高位bit到位bit依次为:符号部分、指数部分、有效数(小数)部分。单精度表示如下,其中符号部分1bit、指数部分8bit、小数部分23bit。
|
|
符号
最高位为符号位,符号位的值为1表示负数,值为0表示正数。
指数部分
将真实的指数值加上一个固定的偏移值,得到指数部分的编码值。将用原码表示的编码值保存在浮点数的指数部分。
对于单精度浮点数,其指数部分位宽为8bit,所以其编码值能够表示的数值范围是0到255;而其偏移值是28−1−1=127;因此真实的指数值能够表示的数值范围是-127到128。事实上-127和128指数会做特殊处理,单精度指数部分的实际取值范围是-126到127,见下面关于数值解析的说明。
有效部分
浮点数的有效部分,也叫小数部分,表示的是一段小数,小数点紧邻在最高位之前,根据数值解析情况的不同,小数点前面的整数为0或者1,这个整数不会被储存。
以单精度为例,其小数部分有23bit,那么根据情况不同,读出的数值可能为(0+编码值∗2−23)或者(0+编码值∗2−23)。
数值解析
规约形式的解析
当指数部分的编码值在[1,28−2]范围,即真实指数值在[−126,127]的范围内时,分数部分小数点前的整数字为1,分数部分表示的值在[1,2)的范围内。例如:
|
|
表示的数值为+1.75∗2−126。
非规约形式的解析
当指数部分的编码值为0时,偏移值为126,真实的指数值为-126,分数部分小数点前的整数字为0,分数部分表示的值在(0,1)的范围内。例如:
|
|
表示的数值为+0.75∗2−126。
这里出现了一个问题,为什么不像规约形式那样,定义上面那个数字为+1.75∗2−127呢?为什么要修改指数和小数部分的解析方式呢?
如果使用统一的规约形式解析,这种表示称为突然式下溢出。按照这种解析方式,绝对值最小的浮点数为+(1+1∗2−23)∗2−127,而小浮点数之间的距离为+1∗2−23∗2−127,当计算两个小浮点数的差时将会得到结果0。如下:
|
|
而使用当前规定的,在指数部分编码值为0时,进行非规约解析的这种表示,称为渐进式下溢出。绝对值最小的浮点数为+(0+1∗2−23)∗2−126,小浮点数之间的距离为+1∗2−23∗2−127。如下:
|
|
特殊值
- 如果指数编码值为0,而且小数部分为0,表示正负0。
- 如果指数编码值为255,而且小数部分为0,表示±Inf。
- 如果指数编码值为255,而且小数部分不为0,表示非数(NaN)。
各种精度的位宽定义
精度 | 符号位 | 指数位数 | 小数位数 |
---|---|---|---|
单精度 | 1 | 8 | 23 |
双精度 | 1 | 11 | 52 |
浮点数的数值比较
指数部分如此设计,优势在于这使得对浮点数的比较更容易,可以按照字典次序比较两个浮点表示的大小,先比较符号,之后是指数的高位、指数的低位、小数的高位、小数的低位。
浮点数的舍入
IEEE标准列出4种不同的舍入方法:
- 舍入到最接近:会将结果舍入为最接近且可以表示的值,但是当存在两个数一样接近的时候,则取其中的偶数(在二进制中是以0结尾的)。
- 朝正无穷方向舍入:会将结果朝正无限大的方向舍入。
- 朝负无穷方向舍入:会将结果朝负无限大的方向舍入。
- 朝0方向舍入:会将结果朝0的方向舍入。
浮点数的运算
标准运算
- 加减乘除。加减运算中+0.0=−0.0
- 平方根。√x≥0(x≥0),√−0.0=−0.0
- 近似到最近的整数round(x)。恰好在中间则近似到偶数。
- 浮点余数。返回x−(round(x/y)∗y)
- 比较运算。−Inf<负规约<负非规约<−0.0<+0.0<正非规约<正规约<+Inf
- 特殊比较。−Inf=−Inf,+Inf=+Inf,NaN与任何浮点数(包括NaN)比较都为假。
精度
单精和双精浮点数的有效数字分别是有存储的23和52个位,加上最左手边没有存储的第1个位,即是24和53个位。 log224=7.22log253=15.95 由以上的计算,单精和双精浮点数可以保证7位和15位十进制有效数字。