fortran90程序设计chapter7.docx
- 文档编号:3541287
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:35
- 大小:202.94KB
fortran90程序设计chapter7.docx
《fortran90程序设计chapter7.docx》由会员分享,可在线阅读,更多相关《fortran90程序设计chapter7.docx(35页珍藏版)》请在冰豆网上搜索。
fortran90程序设计chapter7
第七章循环结构程序设计
循环结构是三种基本控制结构之一。
使用循环结构是优化程序结构的一种有效方法。
本章将详细介绍循环结构及其程序设计方法有关内容。
7.1循环结构概述
7.1.1循环及循环结构
在求解复杂问题时,常常遇到大量重复或相似的处理过程(计算过程、操作过程)。
对于这些处理过程,我们不难按顺序结构设计和编写程序。
例如:
从键盘输入5个数,求5个数之和,并打印输出计算结果。
求解这个问题,我们甚至会不假思索地采用顺序结构设计出求解算法,编写出相应程序。
求解算法如下:
(1)初始化:
赋初值0.0至sum。
(2)输入一个数x,并累加到sum中。
(3)输入一个数x,并累加到sum中。
(4)输入一个数x,并累加到sum中。
(5)输入一个数x,并累加到sum中。
(6)输入一个数x,并累加到sum中。
(7)输出结果sum。
(8)结束。
根据上述算法,编写程序如下:
sum=0.0
READ*,x
sum=sum+x
READ*,x
sum=sum+x
READ*,x
sum=sum+x
READ*,x
sum=sum+x
READ*,x
sum=sum+x
PRINT*,'sum=',sum
END
在上述算法中,第2至第6步的处理过程完全相同。
在程序中,下面2条语句依次重复出现5次:
READ*,x
sum=sum+x
这是一个典型的重复处理问题。
对于这类问题,如果问题规模比较小(如处理5个数),则设计的算法和编写的程序不会感到有何不足之处,相反还给人以简洁、清晰、直观的感觉。
问题是当求解规模增大时(如处理100个数据),则算法中的处理过程“输入一个数x,并累加到sum中”将增加到100个,算法设计人员要机械地重复写100个这样的处理过程,同样程序中的重复语句也增加至100组,程序员要机械地重复写200条这样的语句。
从中可以看出,采用顺序结构不但大大增加了算法和程序长度,增加了存储开销,而且也大大降低了设计算法和编写程序的效率,浪费了程序设计人员宝贵的时间和精力。
求解这类问题的有效办法是采用循环结构,FORTRAN90提供了循环语句用于实现循环结构。
对于上述问题,采用循环结构设计算法如下:
(1)初始化:
赋初值0.0至sum,即0.0sum。
(2)1I。
(3)如果I≤5,则执行步骤(4),否则执行步骤(7)。
(4)输入一个数x,并累加到sum中。
(5)I+1I。
(6)转步骤(3)。
(7)输出结果sum。
(8)结束。
对于上述问题,采用循环语句编写程序如下:
对于顺序结构,其算法步数和程序行数与问题规模成正比,当问题规模从5个数增加到100个数时,算法步数从8步增加至103步,程序行数从13行增加至203行。
而对于循环结构,当问题规模从5个数增加到100个数时,算法步数也是8步,程序行数从13行降低至7行,算法步数和程序行数与问题的规模大小几乎无关。
在算法或程序中,重复地执行某个处理过程或语句块(程序段、语句组)的情形称为循环,被重复执行的处理过程或语句块称为循环体,具有循环特征的程序结构称为循环结构,将重复执行的处理过程或语句块设计成循环结构或编写成循环语句的过程称为循环设计,具有循环结构和循环语句的程序称为循环程序。
[例7.1]求S=1+2+3+…+N的值(N由键盘输入,N>2)。
编写程序。
解:
求解这一问题,将执行N-1次加法运算,如果将等式写成S=0+1+2+…+N,则执行N次加法运算,不同的是参与运算的操作数不同而已。
显然该问题易采用循环结构实现之。
用整型变量S保存和值,用N保存求和最大值,用I作计数器。
编写程序如下:
[例7.2]读入某班级考试成绩(人数不定),计算其平均成绩,并输出。
编写程序。
解:
由于学生人数不定,所以输入的学生成绩个数不确定,以输入-1作为结束标志(因为成绩不可能为负数),从而动态确定学生人数n。
平均成绩计算公式是:
av=(x1+x2+…+xn)/n
对于计算平均成绩问题,核心问题是一个求和问题,类似[例7.1]问题。
程序易采用循环结构和循环语句来实现。
编写程序如下:
从上述例题中可看出,循环结构或循环语句由两部分组成:
一部分是循环体,指需要重复执行的处理过程(语句序列、语句块);另一部分是循环控制机制,指根据条件判断循环体是否继续执行。
7.1.2循环结构分类
循环结构分为两类:
●循环体的循环次数事先确定(如[例7.1]中循环结构),这类循环结构称为确定性循环,或称“计数型”循环,使用计数型循环语句(如DO循环语句)实现这类循环结构。
●循环体的循环次数事先不确定(如[例7.2]中循环结构),这类循环结构称为非确定性循环,或称“条件型”循环,使用条件型循环语句(如DOWHILE循环语句)实现这类循环结构。
条件型循环又分“当型”循环和“直到型”循环。
1.“计数型”循环结构
“计数型”循环是循环体循环次数确定的循环,其循环结构流程图如图7-1所示。
“计数型”循环的功能是:
已知初值、终值和步长。
循环控制变量从初值开始,判断其是否小于等于终值,如果小于等于终值,则执行循环体,执行循环体后,循环变量增加步长,继续判断是否小于等于终值,重复执行以上过程,直到循环变量大于终值,结束循环。
循环次数为:
MAX((终值-初值)/步长+1,0)。
2.“当型”循环结构
“当型”循环是循环体循环次数不确定的循环,其循环结构流程图如图7-2所示。
“当型”循环的功能是:
先判断条件是否成立,当条件成立时,则执行循环体,否则结束循环,即“当条件成立时执行循环体”。
循环次数≥0。
3.“直到型”循环
“直到型”循环是循环体循环次数不确定的循环,其循环结构流程图如图7-3所示。
“直到型”循环的功能是:
先执行循环体,再判断条件是否成立,当条件成立时,则结束循环,否则继续执行循环体,即“执行循环直到条件成立”。
循环次数≥1。
“直到型”循环和“当型”循环的主要区别在于:
“直到型”循环至少执行一次循环体,而“当型”循环则有可能一次也不执行。
一般情况下,对于循环次数大于等于1的同一个问题,既可以用“直到型”循环,也可以用“当型”循环来解决。
图7-1“计数型”循环结构图7-2“当型”循环结构图7-3“直到型”循环结构
对于[例7.2]的问题,如果规定至少有一个学生,则求解该问题的算法可设计成“当型”循环结构,如图7-4所示,也可设计成“直到型”循环结构,如图7-5所示。
图7-4“当型”循环结构图7-5“直到型”循环结构
用DOWHILE循环语句可方便实现“当型”循环结构,而对于“直到型”循环结构,FORTRAN90没有对应的循环语句来实现,可用IF语句和GOTO语句以及无条件DO语句和EXIT语句实现。
用DOWHILE循环语句实现“当型”循环结构的程序上面已经给出,下面给出用IF语句和GOTO语句以及无条件DO语句和EXIT语句实现“直到型”循环结构的两个等价程序:
7.2用DO循环语句实现“计数型”循环
7.2.1DO循环语句
DO循环语句用于实现“计数型”循环结构,语句中直接指定循环的次数和范围。
DO循环语句的一般格式是:
]DO
<语句1>
<语句2>
……
<语句n>
ENDDO[<名字>]
一个DO循环语句称为一个DO循环。
DO循环语句由三部分组成:
DO语句、循环体(语句序列)和ENDDO语句。
DO语句是DO循环的开始语句,指定用于控制循环执行的有关参数(初值、终值和步长),决定是否执行循环体。
循环体是DO循环的主体,给出用于处理数据的有关语句,决定DO循环语句的执行结果。
ENDDO语句是DO循环的终端语句,表明DO循环语句到此结束(注意:
不是循环语句执行结束),控制返回到DO语句执行。
说明:
①v为循环变量,一般为整型变量,用来控制循环次数。
e1、e2和e3为表达式,其类型与循环变量类型相同。
e1代表循环变量v的初值,e2代表循环变量v的终值,e3代表循环变量v的步长,e3可缺省,e3缺省指e3为1。
在DigitalVisualFORTRAN5.0中,v、e1、e2和e3的类型可以是实型,FORTRAN90不提倡使用实型。
下面给出一些合法的DO循环语句:
M=1;N=10;L=1
DOI=1,10,2!
输出1、3、5、7、9
PRINT*,I
ENDDO
DOI=10,1,-2!
输出10、8、6、4、2
PRINT*,I
ENDDO
DOI=M+1,N+2,L+3!
输出2、6、10
PRINT*,I
ENDDO
DOI=1,5!
输出1、2、3、4、5
PRINT*,I
ENDDO
DOA=0.1,0.5,0.1!
输出0.1、0.2、0.3、0.4、0.5
PRINT*,A
ENDDO
②<名字>为DO循环的名称,可选择使用。
为了提高DO循环语句的可读性,可通过<名字>为DO循环语句命名,<名字>后必须跟冒号“:
”。
DO循环语句一旦命名,DO循环语句中的ENDDO语句后必须跟相同的<名字>,否则产生语法错误。
下面给出使用DO循环名字的DO循环语句:
Odd:
DOI=1,10,2!
输出1、3、5、7、9
PRINT*,I
ENDDOOdd
③循环次数计算公式是:
MAX((e2-e1)/e3+1,0)。
⑦如果e3<0,则一般要求e1≥e2,否则循环次数为0,即循环体一次也不执行。
上述DO循环语句的循环次数分别为:
●MAX((10-1)/2+1,0)=MAX(5,0)=5。
●MAX((1-10)/(-2)+1,0)=MAX(5,0)=5。
●MAX((N+2-(M+1))/(L+3)+1,0)=MAX(3,0)=3。
●MAX((5-1))/1+1,0)=MAX(5,0)=5。
●MAX((0.5-0.1))/0.1+1,0)=MAX(5,0)=5。
④e1、e2、e3取值应在循环变量v的取值范围之内。
如循环变量类型为:
INTEGER
(1),取值范围为-128~127,则e1、e2、e3取值应在此范围之内,否则将产生意想不到的错误。
⑤e3不能为0,否则在运行时产生除0错误。
⑥如果e3>0,则一般要求e1≤e2,否则循环次数为0,即循环体一次也不执行。
下面DO循环语句的循环次数为0:
Odd:
DOI=1,10,-2
PRINT*,I
ENDDOOdd
下面DO循环语句的循环次数为0:
Even:
DOI=10,1,2
PRINT*,I
ENDDOEven
⑧在循环体中可引用循环变量v的值,但不能赋值,即修改它的值,对它赋值将产生语法错误。
⑨允许从循环体内受限转移到循环体外,但不允许从循环体外转到循环体内。
下面程序中从DO循环语句内向外转移的操作合法:
Odd:
DOI=1,100,2
IF(I>10)GOTO999
PRINT*,I
ENDDOOdd
999PRINT*,'finishloop.'
END
下面程序中向DO循环语句内转移的操作不合法:
I=1
GOTO999
Odd:
DOI=-100,10,2
999:
PRINT*,I
ENDDOOdd
PRINT*,'finishloop.'
END
下面DO循环语句执行后,I的值为:
11。
最后一行输出结果为:
11。
Odd:
DOI=1,10,2!
输出1、3、5、7、9
PRINT*,I
ENDDOOdd
PRINT*,I!
输出11
END
7.2.2DO循环语句的执行过程
DO循环语句的执行过程:
(1)先对表达式e1,e2,e3分别求值。
若缺省e3,则认为e3=1
(2)e1赋予v。
(3)计算循环次数:
r=MAX(INT((e2-e1)/e3+1),0)
(4)测试循环次数r,若r=0则结束循环,转去执行ENDDO语句后面的第一条可执行语句。
若r>0,则执行循环体直到ENDDO语句。
⑩循环结束后,循环变量v的值有意义,其值为最后一次增加步长后得到的值。
(5)执行ENDDO语句,给循环控制变量v增加一个步长e3,即v+e3v。
循环次数减1,即r-1r,转(4)继续执行。
DO循环语句的执行过程如图7-6所示。
从DO循环语句的执行过程可以看出,在循环体执行前计算循环次数,循环体的执行过程不影响循环次数(转移语句除外)。
循环体中虽然不允许修改循环变量v的值,但允许修改表达式e1、e2和e3中所含变量的值,其修改不影响循环次数。
下面程序中DO循环语句的循环次数为3:
M=1;N=5;L=1
DOI=M,N+5,L+1!
输出1、3、5、7、9
PRINT*,I,M,N,L
M=M+1;N=N*I;L=2*L+I
ENDDO
程序运行后,输出结果为:
1151
3253
53159
747523
9552553
[例7.3]打印5个随机数。
解:
这是一个重复问题,可用循环5次的DO循环语句实现。
REALR
DOI=1,5
CALLRANDOM_NUMBER(R)
PRINT"(1X,F8.3\)",R
ENDDO
END
程序运行后,输出结果为:
0.00000040.02548040.35251620.66691450.9630556
[例7.4]计算4!
并输出。
解:
4!
=1234。
对于n!
计算公式是:
n!
=123…(n-1)n。
该问题显然是一个重复计算问题,需做n-1次乘法。
可用DO循环语句实现。
PARAMETER(n=4)
INTEGER:
:
factor=1
DOi=2,4
factor=factor*i
PRINT*,i,'!
=',factor
ENDDO
END
程序运行后。
输出结果为:
2!
=2
3!
=6
4!
=24
7.3用DOWHILE循环语句实现循环
7.3.1DOWHILE循环语句
DOWHILE循环语句用于实现“当型”循环结构,语句中可给出控制循环执行的条件。
DOWHILE循环语句是一条结构化语句。
DOWHILE循环语句一般情况下用于实现循环次数不确定的循环,也可用它实现循环次数已知的循环,所以该语句有很好的通用性。
DOWHILE循环语句的一般格式是:
]DOWHILE(<循环条件>)
<语句1>
<语句2>
……
<语句n>
ENDDO[<名字>]
一个DOWHILE循环语句称为一个DOWHILE循环。
DOWHILE循环语句由三部分组成:
一个DOWHILE语句、一个循环体(语句序列)和一个ENDDO语句。
DOWHILE语句是DOWHILE循环的开始语句,指出用于控制循环执行的循环条件(逻辑表达式),决定是否执行循环体。
循环体是DOWHILE循环的主体,给出用于处理数据的有关语句,决定DOWHILE循环语句的执行结果。
ENDDO语句是DOWHILE循环的终端语句,表明DOWHILE循环语句到此结束(注意:
不是循环语句执行结束),控制返回到DOWHILE语句执行。
说明:
①<循环条件>可以是关系表达式,也可以是复杂的逻辑表达式,但不能是算术表达式和字符表达式。
下面给出两个使用合法DOWHILE循环语句的程序:
PROGRAMcycle2
sum=0
READ*,x
DOWHILE(0<=x.AND.x<=100)
sum=sum+x
READ*,x
ENDDO
PRINT*,'sum=',sum
END
PROGRAMcycle1
sum=0
READ*,x
DOWHILE(x<>-1)
sum=sum+x
READ*,x
ENDDO
PRINT*,'sum=',sum
END
第二个程序中使用了更严格和复杂的逻辑表达式作为循环控制条件。
②使用DOWHILE循环语句时要特别注意死循环的产生,要保证循环体中至少有一条对循环控制条件有影响的语句,否则将产生死循环,引起严重后果。
上面程序中若将循环体中READ语句误写成PRINT语句,该程序将会产生死循环。
PROGRAMcycle2!
死循环程序
sum=0
READ*,x
DOWHILE(0<=x.AND.x<=100)
sum=sum+x
PRINT*,x
ENDDO
PRINT*,'sum=',sum
END
程序运行时,若第1个输入数据为0至100以内的数,程序产生死循环,无法终止。
7.3.2DOWHILE循环语句的执行过程
DOWHILE循环语句的执行过程:
(1)先计算表示循环控制条件的逻辑表达式或关系表达式的值,结果赋予log。
(2)若log=.TRUE.则执行循环体直到ENDDO语句,否则终止循环,转去执行ENDDO语句后面的第一条可执行语句。
(3)执行ENDDO语句,控制转
(1)继续执行。
DOWHILE循环语句的执行过程如图7-7所示。
图7-7DOWHILE循环语句执行过程
DOWHILE循环语句在每次循环体执行前都要计算表示循环控制条件的逻辑表达式,其计算结果决定循环体是否继续执行,循环体的执行过程必须对循环控制条件产生影响。
[例7.5]求两整数M和N的最大公约数和最小公倍数。
解:
用(Ri,Ri+1)表示Ri和Ri+1的最大公约数,i=1,2,3,…,n,则有:
(R1,R2)=(R2,R3)=…=(Ri,Ri+1)=…=(Rn,0)
其中:
R1=M,R2=N,Rj是Rj-2除以Rj-1的余数,j=3,4,…,n+1,Rn+1=0。
求最大公约数是一个重复计算问题,重复次数不定,可用DOWHILE循环语句实现。
最小公倍数通过最大公约数计算得到,用
编写程序如下:
INTEGERM,N,R1,R2,R3,gcd,lcm
PRINT*,'输入两个自然数:
'
READ*,M,N
R1=M;R2=N
DOWHILE(R2<>0)
R3=MOD(R1,R2)!
求R1除以R2的余数
R1=R2;R2=R3
ENDDO
gcd=R1;lcm=M*N/gcd
PRINT"(1X,I3,'和',I3,'的最大公约数为:
',I3)",M,N,gcd
PRINT"(1X,I3,'和',I3,'的最小公倍数为:
',I3)",M,N,lcm
END
运行程序,输入数据:
9,12↙
程序运行后,输出结果为:
9和12的最大公约数为:
3
9和12的最小公倍数为:
36
7.4用IF和GOTO语句实现循环
用IF语句实现选择结构,用GOTO语句实现无条件控制转移,两者结合可实现循环结构,特别是“直到型”循环结构。
IF语句给出循环条件,GOTO语句控制循环转移。
由于GOTO语句易造成程序错误,故现代程序设计方法不提倡使用此法实现循环。
如[例7.5]问题可用IF和GOTO语句实现,程序如下:
INTEGERM,N,R1,R2,R3,gcd,lcm
PRINT*,'输入两个自然数:
'
READ*,M,N
R1=M;R2=N
100R3=MOD(R1,R2)!
求R1除以R2的余数
R1=R2;R2=R3
IF(R2<>0)GOTO100
!
或IF(R2=0)THEN
!
ELSE
!
GOTO100
!
ENDIF
gcd=R1;lcm=M*N/gcd
PRINT"(1X,I3,'和',I3,'的最大公约数为:
',I3)",M,N,gcd
PRINT"(1X,I3,'和',I3,'的最小公倍数为:
',I3)",M,N,lcm
END
7.5强制性终止循环过程(EXIT、CYCLE)
在前面的示例程序中,循环过程都是正常结束。
有些特殊问题,在循环处理过程中遇到特殊情况需要提前终止本次循环或整个循环,以免循环陷入死循环,造成严重后果。
1.EXIT语句
EXIT语句的功能是:
在循环体执行过程中强制性终止整个循环语句的执行,转循环语句后的第一条语句执行。
只能在DO和DOWHILE循环语句内使用EXIT语句。
给定下面三个示例程序:
!
示例程序一
DOI=1,100,2!
输出奇数1,3,5,7,9
PRINT*,I
IF(I>=9)EXIT
ENDDO
END
!
示例程序三
I=1
DO!
输出奇数1,3,5,7,9
PRINT*,I
IF(I>=9)EXIT
I=I+2
ENDDO
END
!
示例程序二
I=1
DOWHILE(I<=100)!
输出奇数1,3,5,7,9
PRINT*,I
IF(I>=9)EXIT
I=I+2
ENDDO
END
在上述三个示例程序中,从循环控制条件看,要输出100以内的50个奇数,要循环50次,但由于在循环体内设置了EXIT语句,当输出奇数9后循环便强制终止。
EXIT语句不提倡使用,因为它破坏了程序的结构化特性。
有些情况,高水平的设计人员可用EXIT语句简化程序。
合理使用EXIT语句是从死循环中退出的有效途径。
[例7.6]一个猜数游戏。
这个程序随机产生1~10之间的一个整数,用户猜测这个数,并输入到程序中,程序判定并输出猜测结果。
解:
算法描述如下:
(1)产生随机数fun_num;
(2)提示用户输入猜测到的数my_guess,并输入该数;
(3)如果my_guess (4)如果my_guess>fun_num,则猜测数太大,建议猜小一点;继续猜; (5)如果my_guess=fun_num,则猜对了,打印祝贺语; (6)结束。 这是一个重复处理问题,重复次数不确定,只有猜对后才能终止循环。 使用DO循环语句,并在循环体中使用EXIT语句在猜对后强行终止循环的执行。 可用语句CALLBANDOM_NUMBE(R)调用标准子程序BANDOM_NUMBE(R)在0~1的实数范围内产生随机数R。 10*R的范围是[0,10],10*R+1的范围[1,11],也就是1.000000and10.999999之间。 用INT(R)将得到1~10范围的整数值。 编写程序如下: 2.CYCLE语句 CYCLE语句的功能是: 在循环体执行过程中强制性终止本次循环体的执行,转循环语句后的开始语句(DO语句)执行。 只能在DO和DOWHILE循环语句内使用CYCLE语句。 给定下面示例程序: 程序运行后,输出结果为: 223345结束!
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- fortran90 程序设计 chapter7