迭代法也称辗转法,是一种不断用变量的旧值递推新值的过程,跟迭代法相对应的是直接法(或者称为一次解法),即一次性解决问题。迭代法又分为精确迭代和近似迭代。“二分法”和“牛顿迭代法”属于近似迭代法。# M w; h X, l* i
' z" t5 K8 d4 [* e: G% U$ |
迭代算法是用计算机解决问题的一种基本方法。它利用计算机运算速度快、适合做重复性操作的特点,让计算机对一组指令(或一定步骤)进行重复执行,在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的一个新值。 * i; f( {7 ~4 g9 v/ r; v
# G1 |4 r" M" C 利用迭代算法解决问题,需要做好以下三个方面的工作: , u( g% X" a2 U7 M, \2 Z+ `2 }6 k
一、确定迭代变量。在可以用迭代算法解决的问题中,至少存在一个直接或间接地不断由旧值递推出新值的变量,这个变量就是迭代变量。 ; i) V/ J: G( `' g) G- n, t+ Q4 g9 {0 Q$ r* _3 I* l! ?
二、建立迭代关系式。所谓迭代关系式,指如何从变量的前一个值推出其下一个值的公式(或关系)。迭代关系式的建立是解决迭代问题的关键,通常可以使用递推或倒推的方法来完成。 + T4 i2 C. h L1 Q+ L' A+ z' m) A/ D* c5 ?( f I
三、对迭代过程进行控制。在什么时候结束迭代过程?这是编写迭代程序必须考虑的问题。不能让迭代过程无休止地重复执行下去。迭代过程的控制通常可分为两种情况:一种是所需的迭代次数是个确定的值,可以计算出来;另一种是所需的迭代次数无法确定。对于前一种情况,可以构建一个固定次数的循环来实现对迭代过程的控制;对于后一种情况,需要进一步分析出用来结束迭代过程的条件。 ) d: Y* W3 q u9 o: p7 S# p" u. R) y% @! O$ G" ]4 R
例 1 : 一个饲养场引进一只刚出生的新品种兔子,这种兔子从出生的下一个月开始,每月新生一只兔子,新生的兔子也如此繁殖。如果所有的兔子都不死去,问到第 12 个月时,该饲养场共有兔子多少只? % P* _/ T( q. L _9 ^ b9 q( J( r : |/ ?. t: L* `) _ 分析: 这是一个典型的递推问题。我们不妨假设第 1 个月时兔子的只数为 u 1 ,第 2 个月时兔子的只数为 u 2 ,第 3 个月时兔子的只数为 u 3 ,……根据题意,“这种兔子从出生的下一个月开始,每月新生一只兔子”,则有 ) ], s4 Z9 a+ G( V6 x: O1 Q# N* W/ v3 s0 E5 ^) Q
u 1 = 1 , u 2 = u 1 + u 1 × 1 = 2 , u 3 = u 2 + u 2 × 1 = 4 ,…… 9 V5 j- k# D* Y5 U- [/ n
, b5 o' A4 }& `1 S% ?3 [8 A 根据这个规律,可以归纳出下面的递推公式: / Y: e' d: b1 R, G. R4 t, R& }! H* J
/ d1 F* z7 D2 P8 c c% D
u n = u n - 1 × 2 (n ≥ 2) 3 ~/ b2 s/ Z5 z4 ~ 5 z& |' H# j+ |# q6 u9 x6 N1 d. i 对应 u n 和 u n - 1 ,定义两个迭代变量 y 和 x ,可将上面的递推公式转换成如下迭代关系: . C9 h \2 W3 Z+ C% p1 a6 d6 o; o $ A) f% i" m/ |; K y=x*2 # P# R0 a' I U( N* K3 \ & q) K7 ~2 E" \5 t- g. @4 z1 z x=y $ u% t5 a6 O9 d) T# S % F7 N+ Q2 u3 O9 z3 y 让计算机对这个迭代关系重复执行 11 次,就可以算出第 12 个月时的兔子数。参考程序如下: . c" h1 b) _" ?/ I3 s# Y* E, l3 M3 _# D
cls 6 L8 k. o" j; m$ M
+ h( J* V. l3 Q! ^, h0 ^% I& ] x=1 " J# h5 ?/ g. t4 i
* ]/ |- T z4 X8 r; `5 m$ R9 M
for i=2 to 12 X4 X& @ X. _9 ^. ^1 P6 F: M
- h/ o# ]1 P" n5 L1 `8 z y=x*2 $ X( D# j4 F3 { 5 _) t7 V. O, t5 N5 C! i& Z x=y ( O: z# x7 E, R$ f& ]
: Q; ~, l6 i- ~( o' L" l9 F1 U next i 8 @ }; U& n9 n8 R) q; m9 |
+ c }" P! ^( D5 Y print y 1 d% g" F8 }# X( S/ Z * F3 Y. f0 `6 h1 G/ E end $ m# H. K: j) ]7 Q' i9 I3 E
6 u7 p# l" A5 E2 Q, u: P% p$ e 例 2 : 阿米巴用简单分裂的方式繁殖,它每分裂一次要用 3 分钟。将若干个阿米巴放在一个盛满营养参液的容器内, 45 分钟后容器内充满了阿米巴。已知容器最多可以装阿米巴 220,220个。试问,开始的时候往容器内放了多少个阿米巴?请编程序算出。 3 H2 I' ^% `6 I1 Q K: ]" u, _& h1 X
3 v1 y! |* O" n3 S5 F$ G x 14 =x 15 /2 、 x 13 =x 14 /2 、…… x n-1 =x n /2 (n ≥ 1) 6 v' n, E8 c6 t/ N9 s2 c
/ M! L/ u+ i i! c1 m1 p
因为第 15 次分裂之后的个数 x 15 是已知的,如果定义迭代变量为 x ,则可以将上面的倒推公式转换成如下的迭代公式: - p" G+ z: ]$ A. C. M5 K
9 w4 ~) _$ ~# z1 g x=x/2 ( x 的初值为第 15 次分裂之后的个数 2^20 ) & {. V. N! L, G, v3 Q5 O" P: A A [5 B, [" v, \* b( h( E
让这个迭代公式重复执行 15 次,就可以倒推出第 1 次分裂之前的阿米巴个数。因为所需的迭代次数是个确定的值,我们可以使用一个固定次数的循环来实现对迭代过程的控制。参考程序如下: 4 _ o4 N6 v. l Z
' A! W1 E% U. k( K$ o. k( r cls 2 G, t0 m1 s$ Z' v, w2 V
& U/ T6 @2 |2 k3 o. [ e
x=2^20 : H4 N8 [/ A I2 h9 n3 c0 {& c* s3 a! F) @8 d, F% n
for i=1 to 15 * n& {/ J/ J& Y; A, y& B- |* }' C
0 w% p7 b+ y6 a) X! Z' C
x=x/2 $ t* d( P7 u: Z, j5 q$ r; S
! }; V( u+ l: a" y- n next i " B# z$ G1 C/ _4 P$ g( U7 A3 c + D K* J) a1 C print x $ q6 U$ m1 O9 T% t. v% A' k+ B
+ @% |. J8 Q! I
end- v" m# p% L3 S; M7 c
! E7 r( X9 M2 a9 ^% h' V ps:java中幂的算法是Math.pow(2, 20);返回double,稍微注意一下0 n( `9 @# D+ `' Q9 ?# F- c: @- r: s# \
7 P- B& h) f" l+ \! z8 { 例 3 : 验证谷角猜想。日本数学家谷角静夫在研究自然数时发现了一个奇怪现象:对于任意一个自然数 n ,若 n 为偶数,则将其除以 2 ;若 n 为奇数,则将其乘以 3 ,然后再加 1 。如此经过有限次运算后,总可以得到自然数 1 。人们把谷角静夫的这一发现叫做“谷角猜想”。 ) ~' D. O" {- P; @, @: c7 K. d
2 K' }" O% [3 J' S* X4 s9 c- ^2 P
要求:编写一个程序,由键盘输入一个自然数 n ,把 n 经过有限次运算后,最终变成自然数 1 的全过程打印出来。 ' l# h, d" w) x+ }; S ?) v
' C9 N7 \7 A1 I/ a
分析: 定义迭代变量为 n ,按照谷角猜想的内容,可以得到两种情况下的迭代关系式:当 n 为偶数时, n=n/2 ;当 n 为奇数时, n=n*3+1 。用 QBASIC 语言把它描述出来就是: $ p) b, H. i2 G$ o. R; X0 k, v9 u; F0 K
if n 为偶数 then 4 g1 G0 C) ? k; a/ O
4 Z; D6 L- }1 B8 L& q" P
n=n/2 + [ T9 U& c7 \8 w
+ x* I) H3 X/ l2 J) m" e else ; ^# q. d. S3 P% E0 {# L- W( O" W: N8 E$ }3 ~1 \3 } h
n=n*3+1 6 Z( Z) u m$ k$ [' ` ; M- z( j0 o/ N, e* ]: i end if ?- p2 t$ i! e X( I! @
: o5 h/ \- ^$ i/ t V 这就是需要计算机重复执行的迭代过程。这个迭代过程需要重复执行多少次,才能使迭代变量 n 最终变成自然数 1 ,这是我们无法计算出来的。因此,还需进一步确定用来结束迭代过程的条件。仔细分析题目要求,不难看出,对任意给定的一个自然数 n ,只要经过有限次运算后,能够得到自然数 1 ,就已经完成了验证工作。因此,用来结束迭代过程的条件可以定义为: n=1 。参考程序如下: ; A3 M0 N! ~8 u2 g+ b+ O6 \* W+ o& W9 H' e9 e+ F
cls 3 R/ m- N( ~ k* [3 u" R% b
+ s! S( X x8 |) C input "Please input n=";n ( x: m2 H" ?3 \! J& ]
' { N( J/ z& ^& J1 [" V7 K7 O
do until n=1 3 y( R4 E- k" w/ h* Q7 u* N/ |5 [5 l* M
if n mod 2=0 then ' F& L( s" b- B g ! K8 s' i2 X+ j% K+ F2 h3 J/ Z2 C rem 如果 n 为偶数,则调用迭代公式 n=n/2 7 w0 w1 Z7 V" c; P6 x0 L4 E' v3 }8 k% `
n=n/2 ( n+ R X; R7 \+ v7 i) d8 y 4 h4 c9 q) _! k# N& i# M7 r8 T print "—";n; - e3 ^( {( w, H) v ) ]4 \) G0 E1 X! c0 { else " E" L/ s' \$ @
! G4 X4 S; V! K r+ O9 u n=n*3+1 - t) ?5 X( V2 [6 u2 S1 r: h! [9 d4 f4 h2 T
print "—";n; ; g( C" j5 ?/ ^: t, S; x* r+ R1 s8 |. e/ |$ h
end if , Z- m) k6 Z: F# d' O- D& X! Z( m 6 `- E1 S& H: G0 K) W( x loop / ?# _! X/ i y& c 8 U( C' C& M) P4 o: _. Z end # d$ g# ?; N* J $ k% Q& p9 E$ y7 ^5 E6 @ 迭代法 ) R. [; P; _' L" h9 p7 n( k& q* ?: W* k( N9 E v
迭代法是用于求方程或方程组近似根的一种常用的算法设计方法。设方程为f(x)=0,用某种数学方法导出等价的形式x=g(x),然后按以下步骤执行: 6 C( h. I/ t! \
* m1 Y/ ]/ ~- b3 P* R) y1 s
(1) 选一个方程的近似根,赋给变量x0; 4 y: L4 p9 U4 A5 k* F2 u: b3 t @1 b- y0 L( [& O) P6 ]( B (2) 将x0的值保存于变量x1,然后计算g(x1),并将结果存于变量x0; ; }0 x) l- f3 r8 \# }( G
* ^3 P3 ~( s/ `; I& d0 _7 R (3) 当x0与x1的差的绝对值还小于指定的精度要求时,重复步骤(2)的计算。 + l- E9 n; R3 L8 U# m0 a
- p, k* N/ s6 `& J G3 m9 ]
若方程有根,并且用上述方法计算出来的近似根序列收敛,则按上述方法求得的x0就认为是方程的根。上述算法用C程序的形式表示为: 8 V- } t; x; q2 G- e, n8 T: V
【算法】迭代法求方程的根 z! I2 m5 O- {/ a+ `; ? 0 } d8 {* V9 E* U) b" u# m6 K) ^ { x0=初始近似根; $ {8 c% u6 f, R: I8 a. p' l3 x) y 5 q& E6 U+ E {- V# S/ y/ F do { 5 K9 [* a. |3 v7 I
9 B: ]9 q0 [( p! w, _2 ` x1=x0; ' u" m5 F! G$ g
$ K( I/ r9 L& ^- M( x* S x0=g(x1); /*按特定的方程计算新的近似根*/ 0 z; `" }9 U2 w8 z
7 _# L \- V' m+ A5 N' h! k5 D6 k } while ( fabs(x0-x1)>Epsilon); ?5 e3 L# o) X! b . |. }7 p9 S1 [ printf(“方程的近似根是%f\n”,x0); ! f: y. B! u0 z. @" E! |$ K/ M! v% ~
} & h z% ^. Y1 R3 V) w
( C( m. f# H: f$ x
迭代算法也常用于求方程组的根,令 4 u, B9 o# n2 k: f# G, g. ^4 L' F5 \) w( D& }
X=(x0,x1,…,xn-1) & [6 V" w( ?1 I7 T$ x0 O
2 t, g4 a" ^3 u6 z ~& s% Z- e 设方程组为: " e& M% c. W2 J% W n4 J 1 B: y7 K2 W7 [. A1 B D3 `% M xi=gi(X) (I=0,1,…,n-1) # `1 `- W* t9 K# C0 U C0 L' o4 D* H5 ?' x# f$ R% V" k7 r
则求方程组根的迭代算法可描述如下: + i+ ?! W g7 h0 k5 k1 m4 P3 A 3 A. [# G) Y5 N2 a8 w 【算法】迭代法求方程组的根 8 a3 ~- ]- q5 @ k: Z2 v. h5 B5 A1 p0 \0 L, U
{ for (i=0;i * H+ @! Y' @! o8 \5 c2 k- o
5 ]$ H2 c7 h$ \1 j" h
x=初始近似根; 3 B {) g. B+ g3 y, T+ n
9 Y% e6 U6 j6 J% j! x! u4 W
do { 2 N4 [' t& P3 j" c/ {$ m% `
0 M3 A9 J% U f W- g for (i=0;i . ^' q1 w. s7 I7 e 2 L: u( c% {8 s3 y$ }7 ~5 y2 X y=x; - x/ c- L4 X5 E/ T0 R
4 [6 B8 [# F, I) P; t
for (i=0;i . ]7 X! S4 q6 {; o' V 4 ]2 t9 ?8 ^3 x6 m+ V k/ `# j+ f x=gi(X); 5 A) _. u J# v& w0 Y+ E
& [0 i* Z, o* {/ F( ` E for (delta=0.0,i=0;i ; x/ }* G+ V. f: `" h
6 q9 S6 V2 p @! [- y+ T2 f
if (fabs(y-x)>delta) delta=fabs(y-x); $ z, J! v" n! i0 ^4 Z8 n9 Z5 H, Z! V. {1 a" f
} while (delta>Epsilon); / O. S1 l, E2 ]* u1 `! K. O
' i/ f: k0 L) U8 R* K$ d5 U for (i=0;i 8 d* h8 ~. j2 u# C$ L 3 q/ Z: Q0 P( j* m. H w; N2 E printf(“变量x[%d]的近似根是 %f”,I,x); * M: U$ \' W' k6 L/ C