IEEE-754中的舍入方法详解
IEEE-754中的舍入方法详解
在计算机科学中,浮点数的表示和计算是一个核心话题。IEEE-754标准是目前最广泛使用的浮点数表示标准,它定义了浮点数的格式、运算规则以及舍入方法。本文将详细介绍IEEE-754标准中的各种舍入方法及其相关概念,帮助读者深入理解计算机中浮点数的处理方式。
IEEE-754 中的舍入方法
并非所有实数都可以精确地存储为浮点数。考虑一个以归一化浮点数形式表示的实数:x = ± 1. b 1 b 2 b 3 . . . b n . . . × 2 m x = \pm 1.b_1 b_2 b_3 ... b_n ... \times 2^mx=±1.b1 b2 b3 ...bn ...×2m,其中n是尾数中的位数,m是给定浮点数系统的指数。若x没有精确的浮点数表示,则会用最近的两个浮点数x − x_{-}x− 或x + x_{+}x+ 来表示。
为简化讨论,设x为一个正数。在此情形下,有:x − = 1. b 1 b 2 b 3 . . . b n × 2 m x_{-} = 1.b_1 b_2 b_3 ... b_n \times 2^mx− =1.b1 b2 b3 ...bn ×2m和x + = 1. b 1 b 2 b 3 . . . b n × 2 m + 0. 000000...0001 ⏟ n 位 × 2 m x_{+} = 1.b_1 b_2 b_3 ... b_n \times 2^m + 0.\underbrace{000000...0001}{n\text{ 位}} \times 2^mx+ =1.b1 b2 b3 ...bn ×2m+0.n 位000000...0001 ×2m,将实数x替换为附近的机器数(x − x{-}x− 或x + x_{+}x+ )的过程称为舍入,其中涉及的误差称为舍入误差。
IEEE-754 并未明确规定如何舍入浮点数,但有几种不同的方法:
- 向零舍入
- 向正无穷舍入
- 向上舍入
- 向下舍入
- 向最近的浮点数舍入(向上或向下,取决于哪个更近)
- 截断舍入
我们将浮点数表示为f l ( x ) fl(x)fl(x)。上述舍入规则可以总结如下:
x为正数 | x为负数 | |
---|---|---|
向上取整(ceil) | fl(x)=x++向+∞取整 | fl(x)=x--向0取整 |
向下取整(floor) | fl(x)=x--向0取整 | fl(x)=x++向-∞取整 |
截断舍入:f l ( x ) = x − fl(x) = x_{-}fl(x)=x− |
舍入误差
注意,两个机器数之间的差距为:∣ x + − x − ∣ = 0. 000000...0001 ⏟ n 位 × 2 m = ϵ m × 2 m |x_{+} - x_{-}| = 0.\underbrace{000000...0001}_{n\text{ 位}} \times 2^m = \epsilon_m \times 2^m∣x+ −x− ∣=0.n 位000000...0001 ×2m=ϵm ×2m。因此,我们可以使用机器 epsilon 来限制将实数表示为机器数时的误差。
绝对误差
∣ f l ( x ) − x ∣ ≤ ∣ x + − x − ∣ = ϵ m × 2 m |fl(x) - x| \le |x_{+} - x_{-}| = \epsilon_m \times 2^m∣fl(x)−x∣≤∣x+ −x− ∣=ϵm ×2m
∣ f l ( x ) − x ∣ ≤ ϵ m × 2 m |fl(x) - x| \le \epsilon_m \times 2^m∣fl(x)−x∣≤ϵm ×2m
相对误差:
∣ f l ( x ) − x ∣ ∣ x ∣ ≤ ϵ m × 2 m ∣ x ∣ \dfrac{|fl(x) - x|}{|x|} \le \dfrac{\epsilon_m \times 2^m}{|x|}∣x∣∣fl(x)−x∣ ≤∣x∣ϵm ×2m
∣ f l ( x ) − x ∣ ∣ x ∣ ≤ ϵ m \dfrac{|fl(x) - x|}{|x|} \le \epsilon_m∣x∣∣fl(x)−x∣ ≤ϵm
浮点运算的数学性质
- 不一定满足结合律:( x + y ) + z ≠ x + ( y + z ) (x + y) + z \neq x + (y + z)(x+y)+z=x+(y+z),因为f l ( f l ( x + y ) + z ) ≠ f l ( x + f l ( y + z ) ) fl(fl(x + y) + z) \neq fl(x + fl(y + z))fl(fl(x+y)+z)=fl(x+fl(y+z))。
- 不一定满足分配律:z ⋅ ( x + y ) ≠ z ⋅ x + z ⋅ y z \cdot (x + y) \neq z \cdot x + z \cdot yz⋅(x+y)=z⋅x+z⋅y,因为f l ( z ⋅ f l ( x + y ) ) ≠ f l ( f l ( z ⋅ x ) + f l ( z ⋅ y ) ) fl(z \cdot fl(x + y)) \neq fl(fl(z \cdot x) + fl(z \cdot y))fl(z⋅fl(x+y))=fl(fl(z⋅x)+fl(z⋅y))。
- 不一定满足累积性:反复将一个非常小的数加到一个大数上可能没有任何效果。
浮点加法
将两个浮点数相加相对简单。基本思路是:
- 将两个数调整到相同的指数。
- 从前面开始进行小学加法,直到用完系统中的位数。
- 对结果进行舍入。
例如,为了在一个只有 3 位小数部分的浮点系统中将a = ( 1.101 ) 2 × 2 1 a = (1.101)_2 \times 2^1a=(1.101)2 ×21和b = ( 1.001 ) 2 × 2 − 1 b = (1.001)_2 \times 2^{-1}b=(1.001)2 ×2−1相加,这将如下所示:
a = 1.101 × 2 1 b = 0.01001 × 2 1 a + b = 1.111 × 2 1 a=1.101\times 2^1 \b=0.01001\times 2^1\ a+b=1.111\times 2^1a=1.101×21b=0.01001×21a+b=1.111×21
你会注意到,我们加了两个具有 4 位有效数字的数,结果也有 4 位有效数字。浮点加法中没有有效数字的损失。
浮点减法与灾难性消去
浮点减法的工作原理与加法类似。然而,当减去两个大小相近的数时,会出现问题。
例如,为了从a = ( 1.1011 ) 2 × 2 1 a = (1.1011)_2 \times 2^1a=(1.1011)2 ×21中减去b = ( 1.1010 ) 2 × 2 1 b = (1.1010)_2 \times 2^1b=(1.1010)2 ×21,这将如下所示:
a = 1.1011 ? ? ? ? × 2 1 b = 1.1010 ? ? ? ? × 2 1 a − b = 0.0001 ? ? ? ? × 2 1 a=1.1011????\times 2^1\ b=1.1010????\times 2^1\ a-b=0.0001????\times 2^1a=1.1011????×21b=1.1010????×21a−b=0.0001????×21
当我们对结果进行归一化时,得到1. ? ? ? ? × 2 − 3 1.???? \times 2^{-3}1.????×2−3。没有数据可以指示缺失的数字应该是什么。尽管浮点数将存储 4 位小数部分,但它只准确到 1 位有效数字。这种有效数字的损失称为灾难性消去。
示例
考虑函数f ( x ) = x 2 + 1 − 1 f(x) = \sqrt{x^{2} + 1} - 1f(x)=x2+1 −1。当我们在接近零的值处评估f ( x ) f(x)f(x)时,可能会由于浮点减法而遇到有效数字的损失。如果x = 1 0 − 3 x = 10^{-3}x=10−3,使用五位小数算术,f ( 1 0 − 3 ) = 1 0 − 6 + 1 − 1 = 0 f(10^{-3}) = \sqrt{10^{-6} + 1} - 1 = 0f(10−3)=10−6+1 −1=0。
避免有效数字损失的一种方法是消除减法:
f ( x ) = x 2 + 1 − 1 = ( x 2 + 1 − 1 ) ⋅ ( x 2 + 1 + 1 ) x 2 + 1 + 1 = x 2 ( x 2 + 1 + 1 ) f(x) = \sqrt{x^{2} + 1} - 1 = \dfrac{ (\sqrt{x^{2} + 1} - 1) \cdot (\sqrt{x^{2} + 1} + 1) } { \sqrt{x^{2} + 1} + 1 } = \dfrac{ x^{2} } { (\sqrt{x^{2} + 1} + 1) }f(x)=x2+1 −1=x2+1 +1(x2+1 −1)⋅(x2+1 +1) =(x2+1 +1)x2
因此,对于x = 1 0 − 3 x = 10^{-3}x=10−3,使用五位小数算术,f ( 1 0 − 3 ) = 1 0 − 6 2 f(10^{-3}) = \dfrac{ 10^{-6} } { 2 }f(10−3)=210−6 。