浮点算术是一种对由符号、有限精度的有效数和指数表示的数值进行算术运算的方法。它使计算机能够处理数量级跨度很大的数值,而不必存储其间的每一位数字。浮点数构成的是一个有限的可表示数集合,而不是实数那样的连续数系。因此,只要精确结果无法表示,计算就需要舍入。主要标准IEEE 754规定了二进制和十进制格式、运算、舍入行为以及异常条件;具体实现可以采用硬件、软件,或两者结合。(standards.ieee.org)
表示方式与格式
浮点表示法类似于科学记数法。一个有限数值可以表示为
其中, 决定符号, 是有效数, 是基数, 是指数。有效数包含有效数字,指数则决定这些数字对应的数量级。与定点算术不同,基数点相对于所存储数字的位置并不固定。精度和范围是两个独立的属性:有效数的长度限制了能够保留的细节,而指数的范围限制了能够表示的数量级。(docs.oracle.com)
常见的 IEEE 二进制格式采用二进制,各字段以比特编码。对于正规数,有效数的首个二进制位隐含为 1,因此无需显式存储这一位,就能多获得一位精度。(docs.oracle.com)
| 格式 | 总位数 | 指数位数 | 有效数精度 |
|---|---|---|---|
| Binary32,通常称为单精度 | 32 | 8 | 24 位 |
| Binary64,通常称为双精度 | 64 | 11 | 53 位 |
Binary32 可提供约七位十进制有效数字,binary64 则约为十六位。可表示数值的间距并不均匀:在正规数范围内,绝对间距通常随数值的绝对值增大而增大。因此,将一个很小的增量加到足够大的数值上时,这个增量可能会消失。(docs.oracle.com)
舍入与算术运算
IEEE 754 定义了加法、减法、乘法、除法和平方根等基本运算的行为。正确舍入的运算所返回的值,应当等同于先求出精确的数学结果,再将其舍入到目标格式所得的值。这描述的是结果必须满足的要求,并不意味着硬件内部一定采用这样的计算过程。(docs.nvidia.com)
二进制运算的默认舍入方向是舍入到最近值;如果精确结果恰好位于两个可表示值的中点,则选择有效数末位为偶数的那个结果。定向舍入模式则分别向正无穷、负无穷或零舍入。融合乘加计算 时,只在最后舍入一次,而不是先将乘积舍入,再加上 。因此,它可能得到与分别执行乘法和加法不同、且更准确的结果。(docs.nvidia.com)
表示误差在算术运算开始之前就已经产生。例如,十进制小数 的二进制展开是无限循环的。在通常的 binary64 求值方式下,0.1 + 0.2 得到的值一般显示为 0.30000000000000004。这反映了操作数的近似表示以及求和时的舍入,而不是某种无缘无故的故障。十进制算术可以精确表示这些特定的输入,但在十进制精度有限的情况下, 等结果仍然需要舍入。(docs.python.org)
特殊值与异常
IEEE 格式包含正零和负零、正无穷和负无穷,以及NaN 值。在普通的数值比较中,带符号的两个零相等,但它们仍保留不同的符号,而这些符号可能影响后续运算。NaN 用于表示无效运算的结果,例如零除以零;涉及 NaN 的普通相等比较都为假,包括 NaN 与自身的比较。(docs.oracle.com)
次正规数位于零与最小正正规数之间。随着绝对值减小,它们保留的有效数字逐渐减少,从而实现渐进下溢,而不是突然跳变为零。IEEE 算术区分五种异常条件:无效运算、除以零、上溢、下溢和不精确结果。默认处理方式通常是给出一个结果并记录状态标志,而不一定终止执行。编程语言环境可能规定额外的行为。(docs.oracle.com)
数值误差与稳定性
舍入误差通常用相对误差或末位单位来衡量,后者缩写为 ulp。机器 epsilon通常指 1 与比它大的下一个可表示值之间的间距,不过不同约定下的定义有所差异。这些度量描述的是算术精度,并不能给出整个计算准确度的通用界限。(docs.oracle.com)
浮点加法通常不满足结合律: 可能与 不同。两个几乎相等的近似值相减,可能导致灾难性消去,使先前的误差在仅剩的几位数字中显现出来。不过,对于已存储的操作数而言,这次减法本身仍可能是精确的。(docs.nvidia.com)
数值稳定性关注的是算法如何传播误差。它不同于问题的条件数,后者衡量问题对输入变化的敏感程度。与直接逐项累加相比,成对求和与补偿求和可以减少误差。这些区别对数值线性代数及其他数值计算至关重要。(docs.oracle.com)
并行计算与混合精度
在并行计算中,改变归约树会改变加法的执行顺序,并可能使最终结果的某些比特发生变化。编译器变换、中间计算精度以及融合运算的使用,也会影响数值结果的可复现性。仅仅使用相同的数学公式,并不能保证在不同执行环境中得到相同的浮点结果。(docs.nvidia.com)
混合精度算术在同一次计算中结合使用多种格式。在机器学习中,可以将低精度乘法与较高精度的累加相结合,以降低存储和计算成本。Bfloat16浮点格式使用 16 比特,其中指数占八位,有效数精度为八位,包括隐含的首位。它保留了与 binary32 大致相同的正规数指数范围,但数值表示要粗糙得多。(cloud.google.com)