FORTRAN语言题解及分析
[程序说明]
本程序按泰勒展开式计算Sin X的近似值。Sin X的泰勒展开式为
SinX=x_/_1! - x3_/__3! + x5_/__5! - x7_/__7! + …=
计算精度为10-6。程序中T用来存放泰勒展开式中的一项。
[程序]
EPS=1E-6
READ(*,5)X
5 FORMAT(F5.2)
SINX=0.0
T=X
N=1
10 IF( (1) )THEN
SINX=(2)
N=N+1
T=(3)
(4)
(5)
WRITE(*.20)X,SINX
20 FORMAT(1X,'SIN(',F5.2,')=',F14.6)
STOP
END
[答案]
(1) ABS(T).GE.EPS或ABS(T).GE.1E-6
(2)SINX+T
(3)-T*× *× /(2.0*N-2.0)/(2.0*N-1.0)
(4)GOTO 10
(5)ENDIF
[分析]
本题是级数求和问题,应当由一个循环完成求和动作,而在循环之前为预置动值,在循环之后输出结果。由程序可知,该循环应由块IF结构和有关语句构成,(5)应为块IF结构终结语句ENDIF,而(4)应当是GOTO 10,以构成while-do循环结构。 (1)是需要继续循环的条件。由程序说明,计算时要求累加项T有T>=10-6,而舍去 T<10-6的项T。由此,(1)应为ABS(T).GE.EPS,也可以是ABS(T).GE.E-6。如果不用函数ABS,可以是(T.GE.EPS).OR.(T.LE.-EPS)。
(2)是累加和SINX+T。
(3)是新项表达式,由展开式前后项关系,应有T=-T*× *× /(2.0*N-2.0)/(2.0*N-1.0) 注意由(4)、(5)构成的while-do结构,也可以将(4)写为ENDIF,而将(5)写成IF(ABS(T).GE.EPS)GOTO 10,但这种写法使块IF的判断与逻辑IF的判断重复,并不好。
试题二(程序员级下午试题十)
阅读程序
[程序说明](略)
[程序]
SUBROUTINE EXEC(A,M,N,OP,OPE1,OPE2,OPE3,L)
REAL A(M,N,B(1000)
INTEGER OPE1(L),OPE2(L),OPE3(L)
CHARACTER OP(L),CH
DO 10 I=1,L
K=OPE3(I)
(1)
IF (CH.EQ.'I')THEN
WRITE(*.*)'A(',MOD(K-1,M)+1,',',(K-1)/M+1,')='
READ(*.*)(2)
ELSEIF (CH.EQ.'+') THEN
B(K)=(3)
ELSEIF (CH.EQ.'-') THEN
B(K)=(4)
ENDIF
CONTINUE
K=1
DO 20 J=(5)
DO 20 I=(6)
(7)=B(K)
K=K+1
RETURN
END
[答案]
(1) CH=OP(I)
(2) B(K)或 B(OPE3(I)
(3) B(OPE1(I))+B(OPE2(I))
(4) B(OPE1(I))-B(OPE2(I))
(5)1,N 或1,N,1
(6) 1,M 或1,M,1
(7) A(I,J)
[分析]
程序说明非常详细。子程序EXEC的功能是依据输入数据OP、OPE1、OPE2和OPE3,最终求出数组A,从而完成通用表格计算任务。OP(I)、OPE1(I)、OPE2(I)和OPE3(I)是程序说明中最后一个表中的一行数据,代表了 条计算指令。数组B是中间工作数组,B(1),B(2),B(3),……分别对应于A(1,1),A(2,1),A(3,1),……(A元素按先列后行顺序编号),子程序中先求出B,再求A。 观察程序结构,EXEC的执行部分可分为上、下两块。下块由相嵌两层DO循环构成,应是由B元素值求出A元素值,(7)是传送目的地,应为A(I,J),由“先列后行编号”,(5)应为1,N(可为1,N,1),(6)应为1,M(可为1,M,1)。 EXEC前面一块由外层DO循环和内层块IF结构组成,应是产生B元素值的处理过程。在块IF中的判断条件用到变量CH,其值应是指令操作符,应在使用前对CH赋值,因此,(1)应为CH=OP(I)。 (2)是操作符为'I'时读入数据应存入的目的地,它应是相应的B元素之值,(2)应填入B(K)或B(OPE3(I))。 (3)、(4)是加法或减法指令中产生和或差的表达式,应当是两个操作数之和或差。由程序说明,OPE1(I)、OPE2(I)等用于指明表元位置,它们不是操作数,表元值才是操作数。OPE1(I)、OPE2(I)等则相当于操作数的“地址”,(因此,程序说明中将OPE1等称为“操作数”,是不确切的。)操作数则应是相应表元值B(OPE1(I)),B(OPE2(I))等。由此,(3)应为B(OPE1(I))+B(OPE2(I)),(4)应为B(OPE1(I))-B(OPE2(I))
试题三(程序员级下午试题十五)
阅读下列程序说明和FORTRAN程序,把应填入其中空白处的字句,写在答卷的对应栏内。
[程序说明]
欧·乔·马特里克(I·J·MATRIX)博士在十进制数中发现了一组有趣的公式序列:
9×1+2=11
9×12+3=111
9×123+4=1111
… …
9 12345678+9=111111111
我们称10进制数的基为10。同样,对 B(B=2,3, ……)进制数来说,其基为B。本程序对任一基 B(3≤B≤10)是否存在上述性质的公式加以验证。例如 4进制中的公式序列为:
3×1+2=11
3×12+3=111
值得注意的是,这些公式都必须用B进制运算规则计算。 若把公式记为X×Y+Z=W,则程序中X和Z存放在整型变量中,Y和W分别存放在数组N和M中,每个数组元素存放Y或W的一位数字,其中N(1)和M(1)分别存放Y和W的低位数字。
子程序MUL用来实现数组N中的数与整数J相乘,其乘积存贮在数组M中。其中NUM表示N中数的位数,IB为数制的基。子程序ADD用来实现数组M中的数与整数J相加,其和存贮在数组M中,其中NUM和IB的含义同上。
[程序]
INTEGER B,N(100),M(100)
(1)
READ(*,*)B
FLAG=.TRUE.
DO 20 I=1, (2)
DO 30 J=1,
I 30 N(J)=I+1-J
CALL MUL(N,M,B-1,I,B)
CALL ADD ( (3) )
DO 60 K=1,I+1
IF(M(K).NE.1) (4)
60 CONTINUE
20 CONTINUE
IF (FLAG) THEN
WRITE(*,*)'OK.'
ELSE
WRITE(*,*)'ERROR'
ENDIF
STOP
END
SUBROUTINE MUL(N,M,J,NUM,IB)
DIMENSION N(NUM),M(NUM+1)
DO 5 I=1,NUM+1
5 M(I)=0
IC=0
DO 10 I=1,NUM
NN=N(I)*J+IC
(5)
10 M(I)= (6)
(7)
RETURN
END
SUBROUTINE ADD(M,J,NUM,IB)
DIMENSION M(NUM)
(8)
DO 10 I=1,NUM
IF (M(I).GE.IB) THEN
M(I)=M(I)-IB
M(I+1)=M(I+1)+1
ENDIF
10 CONTINUE
RETURN
END
[答案]
(1) LOGICAL FLAG
(2) B-2
(3) M, I+1, I+1, B
(4) FLAG=.FALSE.
(5) IC=NN/IB
或IC=(N(I)*J+IC)/IB
(6) MOD(NN,IB)
或NN-NN/IB*IB
或NN-IC*IB
(7) M(I)=IC
或M(NUM+1)=IC
(8) M(1)=M(1)+J
试题三[分析]
本题程序由3个程序单位组成。主程序验证给定公式左式X*Y+Z之值是不是“全1”,并给出验证结果,输出OK或ERROR。计算X*Y时调用子程序MUL,该乘积与之相加时调用另一个子程序ADD。 主程序中使用变量FLAG标志验证结果,它取值为.TRUE.或.FALSE.,是逻辑变量,应在使用之前说明,因此,(1)应当是类型语句LOGICAL FLAG。而(4)是当存放左式计算结果某一位数值不等于1时的处理,此情况表明验证结果是否定的,与后两块IF的的输出参照,此处应为FLAG=.FALSE.。 (2)作为I的上界值,决定于数制基数B。在说明中,当B=10时右式数字1的数目依次为2,3,4,…,9,此时I值应依次为1,2,…,8,因此(2)应为B-2。 调用MUL计算X*Y之后,调用ADD计算乘积与Z之和。由说明,Z值为2,3,…,即应为I+1。X*Y已存放在数组M各元素中,与Z相同后得到的各位数字仍放在M各元素中。(3)是调用ADD时的实参表,与形参表相对应。形参J应是相加的整数,对应实参为I+1。NUM是数组M原来实有的元素数目,即X*Y乘积的位数,对应实参也应是I+1。IB是数制基数,对应实参应为B。因此,(3)应为M,I+1,I+1,B。 子程序ADD中,(8)之后是对于M(I)的进位处理,表示与J相加的操作应在(8)进行,J应加到表元最低位M(1)中,应填写为M(1)=M(1)+J。至于是否M(1)需要进位,以后如果低位有进位高位是否随之需要进位,则由后面DO循环完成。 现在还有三处填空都在子程序MUL中。这个程序是将数组N表示的IB进制数乘以整数J,乘积的各位数字放在数组M元素中。子程序中变量IC应是进位值,J每和N(I)相乘之后都要考虑到是否进位,(5)应为求进位值的赋值语句IC=NN/IB(整除),(6)则应是从NN中去掉进位值的表达式MOD(NN,IB),或写或NN-IC*IB。(7)在DO循环之后,此时下标最大的M元素应存入进位值,(7)应为M(I)=IC,也可以是M(NUM+1)=IC,但不应是M(I+1)=IC
试题四(高级程序员级下午试题九)
填空
[程序说明]
本程序是一个财务科目汇总的子程序。
科目编号用三位无符号整数表示,例如现金科目的编号为100,则100.1,100.2就是它的二个子目录。而100.1.1是子科目100.1的子科目。本程序中假定一个科目最多有三层子科目。 子程序中,数组SUBJ(4,L)用来存放科目编号,L是系统中科目和子科目的总数(假定L1000)。 规定在数组SUBJ中父科目编号必须位于它的子目录编号之前。子程序中,逻辑数组LD(L)存放相应的科目或子科目的借、贷方类型,.TRUE.表示贷方,.FALSE.表示借方。数组A(L)存放相应科目金额。数组SUBJ、LD和A的值由调用程序提供。其中位于叶结点上的子科目金额已存放在数组A中的相 应位置上,A中其他位置上的值已置为0.0。 子程序中,数组FATHER用记录相应子科目的父科目在SUBJ中的位置(列下标),供汇总时使用。规定对 应于科目的FATHEER元素的值为0。
[程序]
SUBROUTINE RESUME(L,SUBJ,J,A,LD)
INTEGER SUBJ(4,1),FATHER(1000)
REAL A(L)
LOGTCAL LD(L)
DO 20 I=L,1,-1
FATHER(I)=0
IF (SUBJ(2,I).EQ.0) GOTO 20
DO 30 LEN=4,1,-1
IF (SUBJ(LEN,I).NE.0) GOTO 40
30 CONTINUE
40 DO 50 K=I-1,1,-1
IF (1) THEN
DO 60 M=1,LEN-1
IF (SUBJ(M,I).NE.SUBJ(M,K))(2)
60 CONTINUE
(3)
ENDIF
50 CONTINUE
65 FATHER(I)=K
20 CONTHER
DO 70 I=L,1,-1
(4)
IF (K.NE.0) THEN
IF (5) THEN
A(K)=A(K)+A(I)
ELSE
(6)
ENDIF
ENDIF
70 CONTINUE
RETURN
END
[答案]
(1) SUBJ(LEN,K).EQ.0
(2) GOTO 50
(3) GOTO 65
(4) K=FATHER(I)
(5) LD(K).EQU.LD(I)
(6) A(K)=A(K)-A(I)?
试题四分析程序说明详细描述了子程序RESUME所执行的金额“汇总”的意义,以及子程序中变量L、数组SUBJ、LD、A和FATHER的意义,而对于处理过程却没有直接说明,需要通过阅读说明和程序分析出来。 子程序中的数组SUBJ,内容如说明中表中的内容,为4行L列矩阵,每一列表示一个科目或子科目的编号。数组A则提供每个科目或子科目的金额,做为输入值,只提供叶结点科目金额,并在子程序执行后求出其它结点(科目或子科目)金额。 由程序说明,计算每个不是叶结点的科目或子科目的金额时,是求其下一级各结点金额 的代数和。子程序中使用数组FATHER则意味着上述统计是“自下而上”的,即从XUBJ的最后一列依次向前,将每一子科目的金额 加到它的父科目上。 现在来看程序,其执行部分分为上下两块,前一块(从DO 20……到 20 EONTINUE)对于I(取值从L,L-1,……,直至1)求出FATHER(I),后块(从DO 70……到70 CONTINUE)根据FATHER(I)值进行汇总。 在后块中,(6)应为A(K)=A(K)-A(I),与上面A(K)=A(K)+A(I)相对应,分别处理汇总时相加(同为借方或贷方)及相减(一方为借方,一方为贷方)的问题。某一方是借或贷用LD元素标志,因此,条件(5)应为LD(I).EQU.LD(K)。(4)应给出后面所用的K值,它应是I对应的父结点编号,(4)应定为K=FATHER(I)。
子程序的前块确定FATHER(I)值。它是由内层循环(从DO 50 K=I-1,1,-1到50 CONTINUE)进行搜索的,前3个空也恰好在这个内层循环中。最内层循环(从DO 60……到60 CONTINUE)是比较SUBJ第I列和第K列同一行元素(从第I至第LEN-1行是否相等,如都相等,则第I列是第K列子结点,即第K列是第I列子结点,否则,只要有一处不相等,就没有上述父子结点关系。由此,(2)应为GOTO 50(继续考察下一个第K列),而(3)应跳出K循环,认定当前K值即为所求父结点科目(子科目)列号,应填入GOTO 65。(1)是对于第K列进一步考察的条件,它要求第K列有可能是第I列的父结点。此时已知SUBJ(LEN,I)是第I列中行下标最大的非零元素,而程序说明指出其父结点的第LEN行下标应当为0,即如果第K列SUBJ元素是所寻找的父结点,必须有SUBJ(LEN,K)为0,因此(1)应填写为SUBJ(LEN,K)。EQ。O