5.14 関数と手続き
5.14.3 手続きと関数の例
Example 5.14.1 以下の手続きと,それを呼び出しているプログラムは,与えられた2つのinteger型の 変数のうち小さくない方を表示するものである.
program print_max (output) ; var
x,y : integer ;
procedure print_max(x,y : integer) ; var
z : integer ; begin
if (x < y) then writeln(y) else
writeln(x) ; end ;
begin x := 1 ; y := 2 ; print_max(x,y) end.
Example 5.14.2 この例では,2つのinteger型の変数の和を返す関数を記述している.
program print_sum (output) ; var
x,y : integer ;
function return_max(x,y : integer) : integer ; begin
return_max := x + y ; end ;
begin x := 1 ; y := 2 ;
writeln(return_max(x,y)) end.
Example 5.14.3 この例は,配列をベクトルと思い,それの長さを返し, さらに,それに直交するベクトル を一つ求めている11 .
11本当はちょっと問題のある計算である.
Id: P6.tex,v 1.5 2001-03-15 15:43:57+09 naito Exp
program vector (output) ; type
vector = array [1..2] of real ; var
x,y : vector ; r : real ;
function get_norm_and_normal (a : vector ; var b : vector) : real ; begin
b[1] := a[2] ; b[2] := (-1)*a[1] ;
get_norm_and_normal := sqrt(a[1]*a[1] + a[2]*a[2]) ; end ;
begin
x[1] := 1.0 ; x[2] := 0.0 ;
r := get_norm_and_normal(x,y) ;
writeln(’length of (’,x[1],’,’,x[2],’) = ’,r) ;
writeln(’normal of (’,x[1],’,’,x[2],’) = (’,y[1],’,’,y[2],’)’) ; end.
このように,関数の結果型とはなり得ないものを求めるには,関数もしくは手続きの副作用を利用するこ とができる.
Example 5.14.4 この例は,異なった関数に対して,f(x) +g(y/2)の値を求める関数である.
program sum_of_function_values (output) ; var
x,y : real ;
function sin_ft(a : real) : real ; begin
sin_ft := sin(a) ; end ;
function cos_ft(a : real) : real ; begin
cos_ft := cos(a) ; end ;
procedure ch(var a : real) ; begin
a := a/2.0 ; end;
function sum_of_function_values ( a,b : real;
procedure ch (var a : real) ; function f(a : real) : real ;
function g(a : real) : real ) : real ; begin
ch(b) ;
sum_of_function_values := (f(a) + g(b)) ; end ;
begin
x := 0.0 ; y := 1.0 ;
writeln(x,y,sum_of_function_values(x,y,ch,sin_ft,cos_ft)) ; end.
Example 5.14.5 この例は,上の例と同じ結果をもたらすが,forwardを利用している.
Id: P6.tex,v 1.5 2001-03-15 15:43:57+09 naito Exp
program sum_of_function_values (output) ; var
x,y : real ;
procedure ch(var a : real) ; forward ; function sin_ft(a : real) : real ; begin
sin_ft := sin(a) ; end ;
function cos_ft(a : real) : real ; begin
cos_ft := cos(a) ; end ;
function sum_of_function_values ( a,b : real;
function f(a : real) : real ;
function g(a : real) : real ) : real ; begin
ch(b) ;
sum_of_function_values := (f(a) + g(b)) ; end ;
procedure ch ; begin
a := a/2.0 ; end;
begin
x := 0.0 ; y := 1.0 ;
writeln(x,y,sum_of_function_values(x,y,sin_ft,cos_ft)) ; end.
5.14.4 再帰的関数呼びだし
前のsectionで解説した関数,手続きは,それ自身をその内部で呼び出すことができる. これを再帰的関
数呼び出し(recursive function call)と呼ぶ.
再帰的関数呼び出しを利用すると, 帰納的に定義されたものを計算することが容易になる. 数学的には, 再帰で計算できるものは必ず再帰を利用しなくても計算できることが証明されているが,再帰で計算する とプログラムが簡潔になるという利点がある. 一方, 関数,手続き等を呼び出す際には, 多くの処理系にお いて呼び出しの手順として時間がかかることが多い. したがって,再帰には時間がかかることが多い.
Example 5.14.6 次は,帰納的に定義された数列an+1=an+ 2,a1= 1のan を求める関数である.
function recursive_function(n : integer) : integer ; begin
if (n = 1) then
recursive_function := 1 else
recursive_function := recursive_function(n-1) + 2 ; end ;
再帰を用いたアルゴリズムは,必ず再帰を用いなくても実現できる. 再帰を用いると,メモリ内のスタック
(stack)領域を大量に消費する. したがって,あらかじめどのくらいの回数の再帰が行われるかを見積もり,
余りに回数が多い場合には,再帰以外の方法を考えた方が良い場合もある.
Id: P6.tex,v 1.5 2001-03-15 15:43:57+09 naito Exp