J.12 历史回顾与参考文献
最早的计算机使用定点而非浮点。Burks、Goldstine 与 von Neumann [1946] 在《电子计算装置逻辑设计的初步讨论》中写道:
“浮动”小数点系统似乎有两个主要目的,两者都源于一个事实:每台机器每字的数字位数,是由设计考虑确定的常数。第一个目的,是在和或积中尽可能保留更多有效数字;第二个目的,是减轻人工估算并在问题中插入“比例因子”的负担。
比例因子是乘法常数,用来让数值保持在机器可表示范围内。
当然,引入适当比例因子的安排会耗费人的时间,这是无法否认的。我们只是认为,与为机器准备一个有意义的问题所耗的总时间相比,这部分时间所占比例很小。我们觉得浮点的第一个好处多少有些虚幻:为了支持浮点,必须牺牲本可用来让每字保存更多数字的存储容量。因此,浮动二进制小数点的有限好处,能否抵偿存储容量损失,以及算术和控制电路复杂性的增加,在我们看来并不明确。
这让我们看到了早期设计者的立场:节省计算机时间和存储,比节省程序员时间更重要。
最早介绍 Wallace 树、Booth 重编码、SRT 除法、重叠三位组等技术的论文,收录于 Swartzlander [1990]。Anderson 等 [1967] 很好地介绍了早期 IBM 360/91,它使用流水化 Wallace 树、Booth 重编码和迭代除法。Freiman [1961] 分析逐位 SRT 的平均时间,是少数未收入该论文集、却很有价值的历史论文之一。
Mead 与 Conway [1980] 的经典教材认为 CLA 在 VLSI 中成本效益不佳,不鼓励采用。Brent 与 Kung [1982] 的重要论文帮助改变了这一看法。详细 CLA 版图见 Ngai 与 Irwin [1985] 或 Weste 与 Eshraghian [1993],更理论化的分析见 Leighton [1992]。Takagi、Yasuura 与 Yajima [1985] 详细介绍了带符号数字树乘法器。
IEEE 算术占主导之前,浮点格式很多,重要者包括 IBM 370、DEC VAX 和 Cray。VAX 最接近 IEEE:单精度 F 格式也有隐含位、8 位指数、23 位小数部分,但没有 sticky 位,中点总向上舍入而不是取偶。指数范围略有不同:,IEEE 为 −126;,IEEE 为 127。主要区别是缺少特殊值与渐进下溢。VAX 的保留操作数类似 signaling NaN,引用它就触发陷阱。最初双精度 D 格式也只有 8 位指数,对许多应用太少,所以后来增加 G 格式,与 IEEE 双精度一样有 11 位指数。VAX 还有 128 位 H 格式。
IBM 370 使用十六进制而非二进制,因此不能使用隐含首位。单精度含 7 位指数与 24 位小数,即 6 个十六进制数字。原书据此写出最大可表示数为
并与 IEEE 的 比较。十六进制规格化只要求首个十六进制数字非零,换成二进制后,最高三位仍可能为零,因此有效精度可能少于 24 位。采用较高基数,是为了减少浮点加法时的移位量;但在运算时间通常不依赖操作数的机器中,这一优势已不那么重要。
译注:上述“最大可表示数”公式为原页原式,只由指数域位数作了数量级比较,未计实际指数偏置、端点和有效数,不能当作两种格式的精确最大有限值;本附录图 J.7 给出的 IEEE 单精度最大无偏置指数为 127。
370 也没有舍入位与 sticky 位,效果上是截断而非舍入,许多计算结果会系统性偏小。它与 VAX、IEEE 还有一点不同:所有位模式都是合法数值。因此,库函数必须另行约定出错时返回什么。例如 IBM FORTRAN 库对 竟返回 2!
Cray 算术很有意思,因为它一切以最高浮点性能为目标。指数域 15 位,小数域 48 位。加法没有保护位,乘法比加法更不准确。若把乘法看成 p 个、每个 2p 位的数相加,Cray 会丢弃每个加数的低位,因此不容易分析准确误差。倒数用迭代计算,a/b 则以 a 乘 1/b;两种误差叠加,使除法的最后三位不可靠。至少,Cray 迫使数值分析人员始终保持警觉!
IEEE 标准化始于 1977 年,主要由 W. Kahan 推动,部分基础来自他在多伦多大学 IBM 7094 上的工作 [Kahan 1968]。过程漫长,渐进下溢争议最大。Cleve Moler 曾说,有人建议赴美游客千万别错过三个景点:拉斯维加斯、大峡谷,以及 IEEE 标准委员会会议。标准终于在 1985 年获批。
Intel 8087 是第一个重要商业 IEEE 实现,1981 年就已问世,早于标准定稿,因此保留了最终标准删除的特性,例如 projective bits。据 Kahan 说,扩展双精度的长度取决于 8087 能实现什么。IEEE 并非直接基于某个既有系统,但多数特性在其他系统出现过:CDC 6600 为 INDEFINITE、INFINITY 保留特殊位模式,非规格化数思想见 Goldberg [1967] 与 Kahan [1968]。Kahan 因其浮点贡献获得 1989 年图灵奖。
浮点很少成为大众媒体焦点,但 1994 年 11 月,报纸却充满了浮点除法的报道。
Intel 当时所有 Pentium 芯片的除法算法出现缺陷。发现者是 Virginia 州 Lynchburg College 的数学教授 Thomas Nicely,他在计算素数倒数时遇到了问题。消息首先刊登在 11 月 7 日的 Electronic Engineering Times 头版。
Intel 起初拒不正视,声称只影响理论数学家,并对媒体说:“这甚至算不上勘误……即使你是工程师,也不会遇到它。”压力增大后,Intel 于 11 月 30 日发布白皮书,解释为何认为缺陷不严重。理由之一是:随机选两个浮点数相除,商出错的概率约九十亿分之一。但 Intel 没有解释,为何认为普通客户会随机使用浮点数。
压力持续上升。一个尤其令人不满的事实是,Intel 在 Nicely 之前已知道问题,却决定不公开。最终,12 月 20 日,Intel 宣布无条件更换使用错误算法的 Pentium,并计提一笔当时未公布金额的费用,后来确定为 3 亿美元。
Pentium 采用 J.9 节介绍的简单 SRT 变体。错误出在把商选择表转换为 PLA 时:Intel 显然认为,几个商数字为 2 的表项永远不会被访问,于是据此优化,让这些位置输出 0。然而它们实际会被访问,导致错误。虽然 2048 项中只有 5 项错误,随机输入的错误商概率仍为九十亿分之一。习题 J.34 会进一步研究。
本附录完整书目见后面的“参考文献”页。