迭代法也称辗转法,是一种不断用变量的旧值递推新值的过程,跟迭代法相对应的是直接法(或者称为一次解法),即一次性解决问题。迭代法又分为精确迭代和近似迭代。“二分法”和“牛顿迭代法”属于近似迭代法。 ) m" q) e6 t' {& Y/ W+ p* C 5 g+ A. ?7 ]( e0 A- y 迭代算法是用计算机解决问题的一种基本方法。它利用计算机运算速度快、适合做重复性操作的特点,让计算机对一组指令(或一定步骤)进行重复执行,在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的一个新值。 - y8 x5 |6 V, G. r4 A, N' E3 R O. `: m4 d6 ~6 [
利用迭代算法解决问题,需要做好以下三个方面的工作: * W' J4 ?9 P) b$ b% h- s / s8 @, j2 y" K& X1 x6 m 一、确定迭代变量。在可以用迭代算法解决的问题中,至少存在一个直接或间接地不断由旧值递推出新值的变量,这个变量就是迭代变量。 , Q: h: @' F y3 i/ [% p& f- L
, A& @$ _7 i" U8 w8 \$ k 二、建立迭代关系式。所谓迭代关系式,指如何从变量的前一个值推出其下一个值的公式(或关系)。迭代关系式的建立是解决迭代问题的关键,通常可以使用递推或倒推的方法来完成。 / x7 X& s+ r5 X
& s1 S" m; C' b
三、对迭代过程进行控制。在什么时候结束迭代过程?这是编写迭代程序必须考虑的问题。不能让迭代过程无休止地重复执行下去。迭代过程的控制通常可分为两种情况:一种是所需的迭代次数是个确定的值,可以计算出来;另一种是所需的迭代次数无法确定。对于前一种情况,可以构建一个固定次数的循环来实现对迭代过程的控制;对于后一种情况,需要进一步分析出用来结束迭代过程的条件。 4 \+ Z; \' u$ \9 G0 B3 v# k1 n2 z! e) W: x1 @$ F" o
例 1 : 一个饲养场引进一只刚出生的新品种兔子,这种兔子从出生的下一个月开始,每月新生一只兔子,新生的兔子也如此繁殖。如果所有的兔子都不死去,问到第 12 个月时,该饲养场共有兔子多少只? 7 \! s$ S2 R# [- y6 a ) @& H/ a; X1 R2 L) E- q 分析: 这是一个典型的递推问题。我们不妨假设第 1 个月时兔子的只数为 u 1 ,第 2 个月时兔子的只数为 u 2 ,第 3 个月时兔子的只数为 u 3 ,……根据题意,“这种兔子从出生的下一个月开始,每月新生一只兔子”,则有 , X- a' _- ?' Z# g ) K+ B3 _0 n' o3 {& n$ J u 1 = 1 , u 2 = u 1 + u 1 × 1 = 2 , u 3 = u 2 + u 2 × 1 = 4 ,…… * R2 U0 \9 ?" z8 S2 N8 I( w# L
* Z$ F" ^0 O8 |
根据这个规律,可以归纳出下面的递推公式: ( t! _" a# M2 m4 C/ z; w) |2 H* i4 p$ B7 @# v
u n = u n - 1 × 2 (n ≥ 2) " L! U9 i% F! b* r& \: ^+ R* n4 _/ I2 i
对应 u n 和 u n - 1 ,定义两个迭代变量 y 和 x ,可将上面的递推公式转换成如下迭代关系: 3 c+ T( f5 C. J+ s$ e9 T$ Z: N* J7 W6 Y2 O `. |2 L4 c* f
y=x*2 # R" a% _/ d+ O1 T$ N3 E
& M1 d+ ~$ s9 |1 l# p x=y . s( r2 Z6 R% l0 ~' l) I6 l! r& w3 h+ P% O% e" e
让计算机对这个迭代关系重复执行 11 次,就可以算出第 12 个月时的兔子数。参考程序如下: $ Q }, K: r# F, x) P
" D. b( A" F) o5 Q: V0 T
cls + t* O1 z4 l: \8 G 3 L2 k1 f- M+ N3 [ x=1 ! K* c4 Q* x2 p/ x8 o' ~4 _) H9 ]- Q1 w% B
for i=2 to 12 , S' V8 H' L; U! J8 r% N% ?) c
o- ]; a, K$ `1 r6 G! p4 h y=x*2 7 j4 M* o5 O5 Y) d. s m % I/ t: o- K( E' g) L! l( O- i x=y + X. v% @ v8 u* b" q- J/ K/ e# K) Z) }8 j
next i # u" P3 m. n( B' N # x) r! r/ A" P/ d4 C r print y - s" Z# U% d" q: B7 X
* D$ ] y. @2 D5 F# j2 d7 t1 s
end 2 A) K& v& j4 I& _9 K4 g: u / h2 s; f3 {! i 例 2 : 阿米巴用简单分裂的方式繁殖,它每分裂一次要用 3 分钟。将若干个阿米巴放在一个盛满营养参液的容器内, 45 分钟后容器内充满了阿米巴。已知容器最多可以装阿米巴 220,220个。试问,开始的时候往容器内放了多少个阿米巴?请编程序算出。 * [# [- m( ^/ q* I. f& ]+ X * q5 U& M- _/ j" Y4 m 分析: 根据题意,阿米巴每 3 分钟分裂一次,那么从开始的时候将阿米巴放入容器里面,到 45 分钟后充满容器,需要分裂 45/3=15 次。而“容器最多可以装阿米巴2^ 20 个”,即阿米巴分裂 15 次以后得到的个数是 2^20 。题目要求我们计算分裂之前的阿米巴数,不妨使用倒推的方法,从第 15 次分裂之后的 2^20 个,倒推出第 15 次分裂之前(即第 14 次分裂之后)的个数,再进一步倒推出第 13 次分裂之后、第 12 次分裂之后、……第 1 次分裂之前的个数。 6 q6 z/ p% _( y5 ~
2 b& p: t/ _8 S! V( h* d
设第 1 次分裂之前的个数为 x 0 、第 1 次分裂之后的个数为 x 1 、第 2 次分裂之后的个数为 x 2 、……第 15 次分裂之后的个数为 x 15 ,则有 5 e8 p, F; n! ]* J# p# N& e2 ~4 Z
! k1 I; x$ K; d; V. V4 Z$ W7 w
x 14 =x 15 /2 、 x 13 =x 14 /2 、…… x n-1 =x n /2 (n ≥ 1) ) K2 |. t1 H; x b& v1 |5 y 6 i- X& d& m' z9 b( z 因为第 15 次分裂之后的个数 x 15 是已知的,如果定义迭代变量为 x ,则可以将上面的倒推公式转换成如下的迭代公式: * y0 m+ Z2 X0 T
3 {8 {$ e4 H$ T! y x=x/2 ( x 的初值为第 15 次分裂之后的个数 2^20 ) 4 F, J/ i' q/ Z9 w7 D" x
- Y* i' z* v, h! A5 k
让这个迭代公式重复执行 15 次,就可以倒推出第 1 次分裂之前的阿米巴个数。因为所需的迭代次数是个确定的值,我们可以使用一个固定次数的循环来实现对迭代过程的控制。参考程序如下: 6 r: |& P; [ L
" _$ p, u0 G# t& N v+ r cls . m- G* F% W* c, A8 |6 t& P , y: ~: O0 ~" x# ]/ O3 k x=2^20 6 m, [& B& E6 z6 ?! e
, `1 j, P0 ?$ d( i' H. T
for i=1 to 15 7 Z' o, I4 _0 o$ V+ N: x! z * v0 O r6 I4 S: c9 K* k x=x/2 6 d. X% h c) o9 N$ g$ A9 ~
+ e. W; T# m1 m3 o$ z
next i f* ]0 D8 c8 m! G, T! B' W- o) t, w0 Q, Y
print x - p# J6 q2 w+ v
* s# G! l9 E. R5 N+ ^! j5 j
end! Q) E& n8 u* `( ?
O7 s7 [" w2 j3 e B ps:java中幂的算法是Math.pow(2, 20);返回double,稍微注意一下' z3 `$ s4 E4 N, t0 `/ \) f
" U) z) n- H. @( N) ?! P2 z% j
例 3 : 验证谷角猜想。日本数学家谷角静夫在研究自然数时发现了一个奇怪现象:对于任意一个自然数 n ,若 n 为偶数,则将其除以 2 ;若 n 为奇数,则将其乘以 3 ,然后再加 1 。如此经过有限次运算后,总可以得到自然数 1 。人们把谷角静夫的这一发现叫做“谷角猜想”。 + N* U+ M J5 x5 F. C. F2 P2 q
7 R& {! ~! A2 V0 m. F6 l; m! n) x 要求:编写一个程序,由键盘输入一个自然数 n ,把 n 经过有限次运算后,最终变成自然数 1 的全过程打印出来。 8 Q8 B' p8 Q" R+ R; _1 u( b) V ; b9 n1 s1 G; F" Z 分析: 定义迭代变量为 n ,按照谷角猜想的内容,可以得到两种情况下的迭代关系式:当 n 为偶数时, n=n/2 ;当 n 为奇数时, n=n*3+1 。用 QBASIC 语言把它描述出来就是: * Q- r4 I# ?, M/ h4 }0 Z Q; H4 e
* j; Y3 T- V( L* A if n 为偶数 then $ S) I5 A6 g p: e f& a; r
( n! r* j. W) H6 U* b6 q2 A% ~
n=n/2 ' U- {) X2 ~9 P3 K* p
2 D9 N* y+ H( O6 z) e U' {, ` else : T1 X. d2 ~% y
4 O7 i/ ^" @5 k6 y n=n*3+1 4 F* K* \) D7 S: o, S4 Z% q; h/ m 7 f( d1 {& u7 a, c- ?; T; E end if # y* v+ l' M* S2 i0 j# y* P$ h6 A: P * f. {( t9 L& Q9 w 这就是需要计算机重复执行的迭代过程。这个迭代过程需要重复执行多少次,才能使迭代变量 n 最终变成自然数 1 ,这是我们无法计算出来的。因此,还需进一步确定用来结束迭代过程的条件。仔细分析题目要求,不难看出,对任意给定的一个自然数 n ,只要经过有限次运算后,能够得到自然数 1 ,就已经完成了验证工作。因此,用来结束迭代过程的条件可以定义为: n=1 。参考程序如下: & O" F' u* O9 n: W/ ^" z( L
5 ~8 m. ^6 r; w: _4 h cls . p9 `1 o- z. P# v q% z; F d$ u' A( i4 v input "Please input n=";n ) G& d; w+ x% G2 S8 n# g- n% H
: H4 y$ r+ G/ s4 C do until n=1 0 i" V0 L/ w+ A- `0 s' |' j1 | 4 k( \/ a2 b% q( K; L& Q+ `# g' o if n mod 2=0 then & l/ j% y" D$ r! d# a# g* c9 ]; i0 }
rem 如果 n 为偶数,则调用迭代公式 n=n/2 ) h) E4 k- R+ F; z
j& }& b/ |/ D1 N+ y3 x. s n=n/2 / B% @" i8 W7 C$ U- S/ j, @) |! m% R* j2 O; n1 E
print "—";n; * a; r$ v: d- R
% m' ?6 ], h) J. {
else + w1 W/ a: W F, [5 A
# J- Y) d. O3 z) i3 h0 j4 W
n=n*3+1 ; j4 S: O7 D2 s4 ~% C: P
) p: w( g* b9 ?9 @ X( {
print "—";n; ' O6 ^# ]" j/ q1 M' a! A
; ~" J6 j' A2 Q$ L6 o$ A f! U% G& | end if 4 }- f4 C I/ F/ W3 O
/ e' `2 |8 N% c* K- y, K" r loop ' d2 ^4 K' d! N' B4 \: n* {( r$ }
2 @) H6 @! s/ q* J" Z
end 9 n1 B' l: {+ T* h
( v: R$ a( {8 c2 p5 V5 w3 S' P 迭代法 * Q/ ]& J8 e9 {+ j: S
6 X& f1 b6 T& q/ j$ c 迭代法是用于求方程或方程组近似根的一种常用的算法设计方法。设方程为f(x)=0,用某种数学方法导出等价的形式x=g(x),然后按以下步骤执行: . T2 `6 j% f& g4 V% _+ _" A+ u
: Z" u9 c1 q7 Q/ m1 N8 O3 w (1) 选一个方程的近似根,赋给变量x0; ; t* h8 c- b' n+ o) q7 C+ s2 F+ Z* w8 z( }2 \
(2) 将x0的值保存于变量x1,然后计算g(x1),并将结果存于变量x0; # m' x! w4 A6 y' t& r4 y$ V& O + q, V& W$ j; v3 N (3) 当x0与x1的差的绝对值还小于指定的精度要求时,重复步骤(2)的计算。 ; q& F; _1 k q0 l) s8 j4 e; b# i3 K" U5 r ~
若方程有根,并且用上述方法计算出来的近似根序列收敛,则按上述方法求得的x0就认为是方程的根。上述算法用C程序的形式表示为: 4 }; W8 I) w! W1 W
- B* O$ d$ B/ I
【算法】迭代法求方程的根 ; j+ `+ ^: J7 A: J7 b+ n : k" ]2 z. U$ s" V2 m, b( [ { x0=初始近似根; T, _; _7 W& d) F3 h4 O3 H9 V# Q8 o- l! z/ a" S0 w
do { ; t( e. @9 e$ Q/ y
* s! u8 z7 t$ O* x } while ( fabs(x0-x1)>Epsilon); - [' q2 W% ^: `* t( |
4 f! G& z" G! P" a' X$ \# h- u
printf(“方程的近似根是%f\n”,x0); ; b" [& G( R. ?( e q/ W ^ Y, H2 K3 v% M, k2 i; |3 g
} ) `3 ^: Q; Y6 Q
6 T! r, |5 t# K7 `
迭代算法也常用于求方程组的根,令 1 }1 ~2 c0 b; p6 H4 n4 G; j 7 o7 [. m8 O7 r* w X=(x0,x1,…,xn-1) 3 @7 B- A( E* W- g# I) F
+ ]9 W, O; o5 B% l
设方程组为: " v6 G/ ~- ~: G* K' \ & J$ R( v0 x, n xi=gi(X) (I=0,1,…,n-1) ( X2 T& E3 P- y2 q/ K. N
# B! r! T, h$ \ |9 K8 ^
则求方程组根的迭代算法可描述如下: 9 p- H) T6 R2 @5 s. A* Z
) {+ r6 ~- q, P+ Q* G
【算法】迭代法求方程组的根 $ [5 o% O7 D( d- r6 v& {+ |8 q, L/ c Y8 w- t% P
{ for (i=0;i 5 q) l1 }2 `7 u( M8 ^, y
0 b/ z# `) A! O+ C6 h, `% f
x=初始近似根; / y( B% d# e' B( w 3 \" ?# x+ W1 c+ f9 S do { : A. a% p# o, l$ d" x- S6 U+ ^# y
+ o; s2 U4 ]' ~0 X8 @$ \! R for (i=0;i & u' G+ X$ W" Q" W$ K % w' Y, [& ^; x- Z& G# k/ p4 ]7 U" A y=x; $ x. t! W: h! i# \/ @" L( y
5 l f5 F1 X6 l4 C7 d for (i=0;i 0 S5 g' Z' O" N
* m/ y; D0 ?- c6 M9 I3 I; u x=gi(X); 1 p% o6 L9 p. A
5 {8 o6 h. M, m' W
for (delta=0.0,i=0;i ) E y+ O: E( u4 I2 R; {" [
( |9 c* G2 H2 G. B- Y3 f if (fabs(y-x)>delta) delta=fabs(y-x); 9 E5 G$ o/ U8 H * b) ~9 B9 f/ N2 C; o1 X) g } while (delta>Epsilon); 4 Q+ D$ A: {, v: X
# W X. p8 Q6 h- ]. a, q& K
for (i=0;i 8 w7 W* I8 t2 k7 R3 {