汇编语言规格化二进制浮点数

大多数二进制浮点数都以规格化格式 (normalized form) 存放,以便将有效数字的精度最大化。给定任意二进制浮点数,都可以进行规格化,方法是将二进制小数点移位,直到小数点左边只有一个“1”。

阶码表示的是二进制小数点向左(正阶码)或向右(负阶码)移动的位数。示例如下:

非规格化 规格化
1110.1 1.1101 X 23
.000101 1.01 X 2-4
1010001. 1.010001 x 26

反规格化数

规格化操作的逆操作是将二进制浮点数反规格化 (denormalize) ( 或非规格化 (unnormalize))。移动二进制小数点,直到阶码为 0。如果阶码为正数 n,则将二进制小数点右移 n 位;如果阶码为负数 n,则将二进制小数点左移 n 位,并在需要位置填充刖导数 0。

实数编码

一旦符号位、阶码和有效数字字段完成规格化和编码后,生成一个完整的二进制 IEEE 段实数就很容易了。首先将设置符号位,然后是阶码字段,最后是有效数字的小数部分。例如,下面表示的是二进制 1.101 x 20
  • 符号位:0
  • 阶码:01111111
  • 小数部分:10100000000000000000000

偏移码 (01111111) 是十进制数 127 的二进制形式。所有规格化有效数字在二进制小数点的左边都有个 1,因此,不需要对这一位进行显式编码。更多的例子参见下表。

二进制数值 偏移阶码  符号、阶码、小数部分
-1.11 127 1 01111111 11000000000000000000000
+1101.101 130 0 10000010 10110100000000000000000
-.00101 124 1 0111110001000000000000000000000
+100111.0 132  0 10000100 00111000000000000000000
+.0000001101011 120 001111000 10101100000000000000000

IEEE 规范包含了多种实数和非数字编码。
  • 正零和负零
  • 非规格化有限数
  • 规格化有限数
  • 正无穷和负无穷
  • 非数字 (NaN,即不是一个数字 (Not a Number))
  • 不定数

不定数被浮点单元 (FPU) 用于响应一些无效的浮点操作。

规格化和非规格化

规格化有限数 (nonnalized finite numbers) 是指所有非零有限值,这些数能被编码为零到无穷之间的规格化实数。尽管看上去全部有限非零浮点数都应被规格化,但是若数值接近于零,则无法规格化。

当阶码范围造成的限制使得 FPU 不能将二进制小数点移动到规格化位置时,就会发生这种情况。假设 FPU 计算结果为 1.0101111 x 2-129

其阶码太小,无法用单精度数形式存放。此时产生一个下溢异常,数值则每次将二进制小数点左移一位逐步进行非规格化,直到阶码达到有效范围:

1.01011110000000000001111 x 2-129
0.10101111000000000000111 X 2-128
0.01010111100000000000011 x 2-127
0.00101011110000000000001 x 2-126

在这个例子中,移动二进制小数点导致有效数字损失了精度。

正无穷和负无穷

正无穷 (+∞) 表示最大正实数,负无穷 (-∞) 表示最大负实数。无穷可以与其他数值比较:-∞ 小于 +∞,-∞ 小于任意有限数,+∞ 大于任意有限数。任一无穷都可以表示浮点溢出条件。运算结果不能规格化的原因是,结果的阶码太大而无法用有效阶码位数来表示。

NaN

NaN 是不表示任何有效实数的位模式。x86 有两种 NaN:quiet NaN 能够通过大多数算术运算来传递,而不会引起异常。signaling NaN 则被用于产生一个浮点无效操作异常。

编译器可以用 signaling NaN 填充未初始化数组,那么,任何试图在这个数组上执行的运算都会引发异常。quiet NaN 可以用于存在调试期间生成的诊断信息。程序可根据需要自由地在 NaN 中编入任何信息。FPU 不会尝试在 NaN 上执行操作。Intel 手册有一组规则确定了以这两种 NaN 为操作数的指令结果。

特定编码

在浮点运算中,常常会出现一些特定的数值编码,如下表所示。字母 x 表示的位,其值可以为 1,也可以为 0。 QNaN 是 quiet NaN, SNaN 是 signaling NaN。

数值 符号、阶码、有效数字
Positive zero 0 00000000 00000000000000000000000
Negative zero 1 00000000 00000000000000000000000
Positive infinity 0 11111111 00000000000000000000000
Negative infinity 1 11111111 00000000000000000000000
QNaN x 11111111 1xxxxxxxxxxxxxxxxxxxxxx
SNaN x 11111111 0xxxxxxxxxxxxxxxxxxxxxx