一、选用算法的原则
原则如下:
- 尽量避免两个相近数相减
- 尽量简化运算步骤、减少运算次数
- 尽量防止大数“吃掉”小数
- 尽量选用数值稳定性好的算法
1、避免两个相近数相减
举几个例子:
- 当 x x x很大时,将算式 1 x − 1 x + 1 \frac{1} {x} - \frac {1} {x+1} x1−x+11换为 1 x ( x + 1 ) \frac {1} {x(x+1)} x(x+1)1
- 当 x x x很大时,将算式 x + 1 − x \sqrt{x+1} - \sqrt{x} x+1−x换成 1 x + 1 + x \frac {1} {\sqrt{x+1} + \sqrt{x}} x+1+x1
- 当 x 1 x_1 x1、 x 2 x_2 x2很接近时,将算式 lg x 1 − lg x 2 \lg x_1 - \lg x_2 lgx1−lgx2换成 lg x 1 x 2 \lg \frac {x_1} {x_2} lgx2x1
2、简化运算步骤、减少运算次数
举个例子:
- 计算多项式函数
p
n
(
x
)
=
a
n
x
n
+
a
n
−
1
x
n
−
1
+
⋯
+
a
1
x
+
a
0
p_n(x)=a_nx^n+a_{n-1}x^{n-1}+ \cdots + a_1x + a_0
pn(x)=anxn+an−1xn−1+⋯+a1x+a0时,可以写成
p
n
(
x
)
=
(
…
(
(
a
n
x
+
a
n
−
1
)
x
+
a
n
−
2
)
x
+
a
n
−
3
…
+
a
1
)
x
+
a
p_n(x) = (\ldots ((a_nx + a_{n-1})x + a_{n-2})x + a_{n-3} \ldots + a_1)x + a
pn(x)=(…((anx+an−1)x+an−2)x+an−3…+a1)x+a
这也是秦九韶算法(递推算法),可以按照下列公式计算: { u n = a n u k = x u k + 1 + a k ( k = n − 1 , n − 2 , ⋯ , 1 , 0 ) p n ( x ) = u 0 \begin{cases} u_n = a_n \\ u_k = xu_{k+1} + a_k & {(k = n-1, n-2, \cdots, 1, 0)} \\ p_n(x)=u_0 \end{cases} ⎩⎪⎨⎪⎧un=anuk=xuk+1+akpn(x)=u0(k=n−1,n−2,⋯,1,0)
3、防止大数“吃掉”小数
为了防止出现“机器零”,也可以给每个数乘一个大的因子,例如乘以10,最后再计算原数值。
4、选用数值稳定性好的算法
举个例子:
- 计算积分
I
n
=
∫
0
1
x
n
e
x
−
1
d
x
(
n
=
0
,
1
,
2
,
⋯
)
I_n = \int _0^1 x^ne^{x-1} \, dx (n = 0, 1, 2, \cdots)
In=∫01xnex−1dx(n=0,1,2,⋯)
如果采用下面的递推算法,虽然 I 0 I_0 I0的近似值误差很小,但是当 n n n很大的时候计算结果往往失真严重,这样的算法,称为数值不稳定的算法。 { I 0 = 1 − e − 1 I n = 1 − n I n − 1 \begin{cases} I_0 = 1 - e^{-1} \\ I_n = 1 - nI_{n-1} \end{cases} {I0=1−e−1In=1−nIn−1
因此应该采用这样的算法: I n − 1 = 1 n ( 1 − I n ) I_{n-1} = \frac {1} {n} (1 - I_n) In−1=n1(1−In)
二、算法稳定性评估
一个算法稳定性的判断,关键是要推导出误差的传播公式。若误差在计算过程中变化大就是不稳定的,否则就是稳定的。