Лекция: Пример 9.6
Используя приведённую выше рекуррентную формулу, вычислить n!
program example96;
var
n, f: integer;
function factorial (m: integer): integer ;
begin
if m=0 then factorial := 1
else factorial := factorial (m — 1) * m
end;
begin
readln (n); f:=fac (n);
write ('факториал ',n:2, '=',f:2)
end.
Замечание. Поскольку n! растет очень быстро, то при n > 7 полученные значения превышают максимально возможное значение типа integer (32767), поэтому рекомендуется n! считать как longint.
Программа содержит два обращения к функции factorial — одно в операторе вызова в главной программе, другое — в операторе присваивания в теле самой функции. Из главной программы функция вызывается один раз. При этом ей передаётся значение фактического параметра n. Для определённости допустим, что n = 3. Итак, функция начинает выполняться со значением формального параметра m = 3. Поскольку m ¹ 0, должна выполниться ветвь else оператора if, т.е. оператор присваивания
factorial := factorial(2)*3. Но правая часть этого оператора содержит обращение к функции factorial, поэтому функция обратится сама к себе с параметром равным 2. Это в свою очередь приведёт к новому обращению к функции с фактическим параметром равным 1.
Таким образом, однократный вызов функции из главной программы приводит к цепочке последовательных незавершенных вызовов этой же функции самой себя. При этом в каждом последующем вызове используется значение формального параметра на 1 меньшее того, что использовалось в предыдущем. Все эти значения запоминаются в разных ячейках памяти. Так будет продолжаться до тех пор, пока значение функции не станет полностью определённым, что произойдёт при значении параметра
m = 0. В этом случае будет выполнен оператор factorial := 1, после чего процесс вычисления факториала начнёт «раскручиваться» в обратную сторону, последовательно выполняя операторы:
factorial(1):=factorial (0)*1
factorial (2):=factorial (1)*2
factorial (3):=factorial (2)*3