上篇文章(传送门)大家可能看得晕晕乎乎的,这篇就来举一些例子来帮助大家更直观的理解 IEEE 754 标准。
本文的举例对象仍然是单精确度浮点数(32位)。
首先回顾一下上篇最后的总结:
形式 | 指数 | 小数部分 |
---|---|---|
零 | 全为 0 | 全为 0 |
非规约形式 | 全为 0 | 大于 0 小于 1 |
规约形式 | 1 到 2ᵉ - 2(不全为 0 也不全为 1) | 大于等于 1 小于 2 |
无穷 | 2ᵉ - 1(全为 1) | 全为 0 |
NaN | 2ᵉ - 1(全为 1) | 非 0 |
non-number
先看那三个简单且很好理解的特殊值:
+0:
0 00000000 00000000000000000000000
-0:
1 00000000 00000000000000000000000
+infinity:
0 11111111 00000000000000000000000
-infinity:
1 11111111 00000000000000000000000
NaN:
s 11111111 fraction
对于 NaN 来说,s 可 0 可 1,fraction 不全为 0 即可
normal number
规约形式的浮点数无疑是日常使用最多的。
例:将 -36.35 转为单精度二进制
- 整数部分转二进制
36₁₀ = (00100100)₂
- 小数部分转二进制
之前的文章说过小数怎么转二进制,再复习一下吧:
- 小数部分乘以 2,取结果的整数部分,直到小数部分为 0 或者位数已达到所要求的精度为止
- 0.35 x 2 = 0.7,整数部分为 0
- 0.7 x 2 = 1.4,整数部分为 1
- 0.4 x 2 = 0.8,整数部分为 0
- 0.8 x 2 = 1.6,整数部分为 1
- 0.6 x 2 = 1.2,整数部分为 1
- 0.2 x 2 = 0.4,整数部分为 0
- 0.4 x 2 = 0.8,从这里开始接下来无限循环 0 1 1 0 …
所以 0.35₁₀ = (01011001100110011000110…)₂
- 计算阶码
整数二进制.小数二进制 = 00100100.01011001100110011000110
移动小数点,使二进制变成 1.xxx * 2ⁿ 的形式:
1.0010001011001100110011000110 * 2⁵
指数的实际值是 5,单精度浮点数的固定偏移值为 127,所以指数域编码值为 5 + 127 = 132。
(132)₁₀ = (10000100)₂,所以阶码为 10000100
- 单精确度浮点数的尾数部分为 23 位,所以取 1.xxx 小数点后 23 位得到尾数部分为:
00100010110011001100110
- 负数符号位为 1,所以 -36.35 的单精度二进制表示为:
1 10000100 00100010110011001100110
例:将 00111001001010111110100000000000
转为小数
- 这是一个正数,是一个规约形式的浮点数,先分为三段
0 01110010 01010111110100000000000
- 计算指数的实际值
(01110010)₂ = 114₁₀,减去单精度浮点数的固定偏移值 127 得指数的实际值为 114 - 127 = -13
- 在尾数前加上隐藏的整数 1,然后转为 1.xxx * 2ⁿ 的形式:
1.01010111110100000000000 * 2⁻¹³
指数实际值为负数,所以整数部分为 0,小数部分二进制为:
0.000000000000101010111110100000000000
- 计算小数
1 | 1 * 2⁻¹³ + 1 * 2⁻¹⁵ + 1 * 2⁻¹⁷ + 1 * 2⁻¹⁹ + 1 * 2⁻²⁰ + 1 * 2⁻²¹ + 1 * 2⁻²² + 1 * 2⁻²³ + 1 * 2⁻²⁵ |
subnormal number
非规约形式的浮点数转换方法其实也很简单。因为非规约形式的浮点数整数部分为 0,所以非规约形式的浮点数转换就相当于上边的小数部分转二进制。
从上篇文章我们知道,非规约形式的浮点数指数实际值为 -126,即最终转为 0.xxx * 2⁻¹²⁶ 的形式,也就是说按照小数部分转二进制的方法,当出现第 127 个数时,这个数就作为尾数的第一个数,后边的依次补上,直到小数部分为 0 或者位数已达到所要求的精度为止。这个就不举例了。
同理,将非规约形式的浮点数转为小数将更简单。
例:将 00000000001000000000000000000000
转为小数
- 这是一个正数,是一个非规约形式的浮点数,先分为三段
0 00000000 01000000000000000000000
- 计算小数
1 | 2⁻¹²⁸ |
怎么样,对于 IEEE 754 的理解是不是更深刻了些?