第10课 函数(二)20080421
调用函数,就是在程序中使用一个函数。如下面PASCAL语句: c:=sqrt(a*a+b*b-2*a*b*cos(alfa)); och:=ord(ch); pch:=pred(ch);
y:=sh(1+sh(x))/(sh(2*x)+sh(3*x));
调用函数的书写一般格式: <函数名>(参数表)
函数的参数可以是常量、变量、表达式。
函数说明的一般形式如下:
FUNCTION <函数名> (<参数表>):<函数类型>; <说明部分>; BEGIN <函数体> END;
函数体对形式参数进行处理,处理结果赋给函数名,作为函数结果传给调用它的程序。所以在函数体中至少应包括一个给函数名赋值的语句:<函数名>:=<表达式>
函数可以没有说明部分。
函数可以没有形式参数,如果没有形式参数,形式参数表和括号应当略去。
在一个形式参数表中,可以有多个参数。逗号用来分开同类型的各个参数名,分号用来分开不同类型的参数。各种类型的参数分别用冒号后的类型标识符说明。例如:
(x:real) (x,y:real)
(x,y:real;m,n:integer)
其中,最后一个参数表中有4个形式参数。x、y是实型参数,m、n是整型参数。 函数定义应写在程序的说明部分,并处于变量说明之后。
在程序中需要调用函数的地方,将函数名和相应的自变量(实在参数)写在表达式中即可。函数调用的一般形式为:<函数名>(<实在参数表>)
函数的形式参数和实在参数:
在说明函数(或称定义函数)时,FUNCTION后面括号中的参数被称为形式参数,简称形参。
在调用函数时,所带的参数被称为实在参数,简称实参。 形式参数存在于说明函数时;实在参数存在于调用函数时。
41
形式参数和实在参数是相互独立的,但它们之间又存在着一 一对应关系。 两者相互独立是指,形参和实参在内存中所占用的存储单元是相互独立的。 如下例中,若读入x=3.29,y=5.71 PROGRAM T85_008; VAR
x,y:real;
FUNCTION max(a,b:real):real; BEGIN
3.29 5.71 { writeln('a1=',a:6:2); 实参
y x writeln('b1=',b:6:2);}
if a
then a:=b;
3.29 5.71 max:=a; 形参
{ writeln('a2=',a:6:2);
a b
writeln('b2=',b:6:2);} END; BEGIN
writeln('Please input two numbers x and y'); write('x=');readln(x); write('y=');readln(y);
writeln('The larger number is ',max(x,y):6:2); { writeln('x=',x:6:2,', y=',y:6:2)} END.
若实参与形参的标识符相同会怎么样呢?实参与形参的标识符可以相同,但在内存中仍然开辟为不同的存储单元。
PROGRAM T85_008;
3.29 5.71 VAR 实参
a,b:real; b a FUNCTION max(a,b:real):real; 参数传递 参数传递 BEGIN if a
then a:=b;
a b max:=a;
END; BEGIN
writeln('Please input two numbers a and b'); write('a=');readln(a); write('b=');readln(b);
writeln('The larger number is ',max(a,b):6:2); END.
形式参数和实在参数之间存在着一 一对应关系是指,实参的数量、数据类型、排列次
42
序都要与形参一 一对应。
在调用函数时,实参的值被传递给形参,最后的函数值传递回主程序。
PROGRAM……
(主程序)
FUNCTION max(a,b:real):real;
(函数)
……
m:=max(x,y);
……
例:定义产生随机数的函数。并借助它生成一些两位整数乘法的算式,让学生回答,计算机给出正确与否的判断。当学生回答为-1时终止运算。
讨论:随机数是在一定范围内任意变化的数。有许多产生随机数方法,我们这里讲的是其中的一种。为了便于使用,将产生随机数定义成函数。该函数产生的随机数是在0~1之间的任意实数。
PROGRAM T85_003; VAR
x,y,z,answer:integer; seed:real;
FUNCTION rand(VAR seed:real):real; CONST a=93.0; m=8192.0; c=1.0; BEGIN
seed:=a*seed+c;
seed:=round((seed/m-trunc(seed/m))*m); rand:=seed/m END; BEGIN
seed:=0.7823; REPEAT
x:=trunc(rand(seed)*100); y:=trunc(rand(seed)*100); write(x:2,'*',y:2,'=?');
43
read(answer); writeln(answer:4); z:=x*y; IF answer=z
THEN writeln('correct!')
ELSE writeln('that is wrong! it is',z); UNTIL answer=-1 END.
在上例中,函数的参数表中的VAR,表明形式参数seed为变量参数。在前面的函数说明中,参数前未加VAR,表明形式参数为值参数。在函数中对值参数的改变不会影响到相应的实在参数。在函数中对就量参数的实际上是对实在参数的运算,因此在函数中改变了变量参数的值,也就改变了相应实在参数的值。
解决有些问题需要有一个产生随机数的函数。 假定问题要在整区间[a··b]集合中随机的选取一个整数r。如[1··2]上表示掷一枚硬币的正面或反面的结果;[1··6]上表示投一粒骰子的面值等。连续掷币,或连续投骰子得到的结果序列:r1, r2, …称为随机序列。
程序不能严格地产生[a··b]上的随机序列,但能用数学方法产生满足应用上所要求的近似随机序列的随机数,通常称为伪随机数。程序产生伪随机数的最通常的方法是线性同余法。
第11课 过程20080428
函数是有局限性的。它们仅可以用于计算单个函数值。这个值是通过函数名带回给调用程序的。而我们常常需要写一些单独的程序模块,回送多个结果。也可能希望写一个模块它不回送任何值,而只执行某些任务,例如打印以前计算的结果,这时用函数就不行了,但是可以用PASCAL提供的过程来解决问题。
一个过程在形式上类似于函数,但它们在定义和使用上又有许多不同。 不同点 开头 回送结果值 函数 以FUNCTION开头 结果值通过函数名回送,且只能回送一个结果值 说明数据类型 需要说明函数类型 主体部分 函数体中至少要包括一个给函数名赋值的语句 调用
44
过程 以PROCEDURE开头 结果值通过参数回送,能回送多个结果值或无结果值 无需说明过程类型 过程体可以为空 函数的调用出现在表达式中 过程的调用必须作为一个单独的语句 例:T85_201 已知三角形的两边a、b及夹角α求对边c及面积s。然后求a+5、b+10、α+15°时的c及s。
讨论:我们可以定义一个已知两边及夹角,求对边及面积的过程。调用它两次,得到问题的解。
根据数学公式有
c?a2?b2?2abcos?
s?1absin? 2用标识符alfa来代替α。下面程序中的红字部分定义了一个已知两边及夹角,求对边及面积的过程。一个过程与函数一样包括过程首部和过程体两部分,其中过程体又可分为过程说明部分和语句部分,下例中没有说明部分。
过程体的通常任务是对值参数进行计算,计算结果赋给变量参数,返回给调用时对应的实在参数。
PROGRAM T85_201; VAR
a,b,alfa,c,s:real;
PROCEDURE cs(a,b,alfa:real;VAR c,s:real); BEGIN
alfa:=alfa*3.14159/180;
c:=sqrt(a*a+b*b-2*a*b*cos(alfa)); s:=0.5*a*b*sin(alfa) END; BEGIN
write('a=?');readln(a); write('b=?');readln(b); write('alfa=?');readln(alfa); cs(a,b,alfa,c,s);
writeln('c=',c:8:2,'; s=',s:8:2); cs(a+5,b+10,alfa+15,c,s);
45