Количество сохранений и максимальная глубина стека, требуемые для вычисления n!
Измерьте количество сохранений и максимальную глубину стека, требуемую для вычисления
n!
при различных малых значениях
n
с помощью факториальной машины, показанной на рисунке 5.11. По этим данным определите формулы в зависимости от
n
для числа сохранений и максимальной глубины стека, требуемых для вычисления
n!
при любом
n > 1
. Обратите внимание, что это линейные функции от
n
, и они определяются двумя константами. Чтобы увидеть статистику, Вам придется добавить к факториальной машине команды для инициализации стека и распечатки статистики. Можно также заставить машину в цикле считывать
n
, вычислять факториал и печатать результат (как для машины НОД с рисунка 5.4), так, чтобы не нужно было все время вызывать
get-register-contents
,
set-register-contents!
и
start
.
(controller
gcd-loop
(assign a (op read))
(assign b (op read))
test-b
(test (op =) (reg b) (const 0))
(branch (label gcd-done))
(assign t (op rem) (reg a) (reg b))
(assign a (reg b))
(assign b (reg t))
(goto (label test-b))
gcd-done
(perform (op print) (reg a))
(goto (label gcd-loop)))
Рис. 5.4. Машина НОД, которая считывает входные числа и печатает результат.
(controller
(assign continue (label fact-done)) ; set up final return address
fact-loop
(test (op =) (reg n) (const 1))
(branch (label base-case))
;; Set up for the recursive call by saving n and continue.
;; Set up continue so that the computation will continue
;; at after-fact when the subroutine returns.
(save continue)
(save n)
(assign n (op -) (reg n) (const 1))
(assign continue (label after-fact))
(goto (label fact-loop))
after-fact
(restore n)
(restore continue)
(assign val (op *) (reg n) (reg val)) ; val now contains n(n - 1)!
(goto (reg continue)) ; return to caller
base-case
(assign val (const 1)) ; base case: 1! = 1
(goto (reg continue)) ; return to caller
fact-done)
Рис. 5.11. Рекурсивная факториальная машина
Комментарии отсутствуют.