凡例:
n 階乗にする数
fn n!の値
fact 階乗を返す関数
■ループを用いた方法
特長:
直感的、シンプル
難点:
グローバル変数の再代入。ただし、グローバル変数を使うこと自体は、
変数管理の厳しいPascalであればさほど気にする必要は無いのかもしれ
ない(関数化は可能だが、あまり意味はなさそうだ)
<repeat-untilループを使った例>
program factorial(output);
var n, fn: integer;
begin
n := 10;
fn := 1;
repeat
fn := fn * n;
n := n - 1;
until n < 2;
writeln(fn);
end.
コメント:repeat文によるループ。次掲のgoto文によるループと基本的には同じ。
単純だが、階乗のような単純構造のプログラムは、この形が案外わかり
やすいのかもしれない。
<goto文を使った原始的なループ>
program factorial(output);
label 100;
var n, fn: integer;
begin
n := 10;
fn := 1;
100:
fn := fn * n;
n := n - 1;
if n > 1 then goto 100;
writeln(fn);
end.
コメント:わざわざgotoループを使っているが、Pascalであればrepeat文か
while文を使うのが自然。構造化機能の無いBASICからの転向者(現代で
はそれもどれくらい居るものなのか?)のための説明コード、といった
ところか。
<whileループを使った例>
program factorial(output);
var n, fn: integer;
begin
n := 10;
fn := 1;
while n > 1 do
begin
fn := fn * n;
n := n - 1;
end;
writeln(fn);
end.
コメント:whileループを使った例だが、階乗計算のような単純なものでれば、
repeatのほうが見やすい。
<forループを使った例>
program factorial(output);
var t, n: integer;
begin
n := 1;
for t:=1 to 10 do n := n * t;
writeln(n);
end.
コメント:ステップ増加式のfor文を使った例。カウンタが素直に使えて見やす
い。
■再帰関数を使った例
特長:
再帰関数を用いる
変数がやや少なくて済む
難点:
際立ったメリットが無いのに書きづらく、わかりづらい
<単純再帰>
program factorial(output);
function fact(n: integer):integer;
begin
if n < 2
then fact := 1
else fact := fact(n - 1) * n
end;
begin
writeln(fact(10));
end.
コメント:再帰の基本形
<末尾再帰>
program factorial(output);
function fact(n, t: integer):integer;
begin
if n < 2
then fact := t
else fact := fact(n - 1, t * n)
end;
begin
writeln(fact(10, 1));
end.
コメント:末尾再帰の基本形。本来、末尾再帰は最適化されてgotoループになる
ことを望むためのものかもしれないが、最適化されない上、goto文が別
に存在するPascalで書く必要は(勉強や遊び以外では)ほとんどない。
■型とリストを使った例
特長:
Pascalの特長である型を駆使
マジカルナンバーの除去
プログラムの修正がしやすい
カウンタの範囲設定により、無限ループを監視できる
難点:
Pascalを知らない人は首をかしげる
<型とリストを使用した例>
program factorial(output);
const
n = 10;
type
length = 1..n;
var
s : array[length] of integer;
c : length;
begin
s[1] := 1;
c := 1;
repeat
c := c + 1;
s[c] := s[c - 1] * c;
until c = n;
writeln(s[n]);
end.
コメント:最後に、Pascalの代名詞とも言える範囲型を導入してみた。確かにコ
ンパイルが必要な言語では、型によるセーフティーネットの安心感は大
きい。