В книге «Структура и интерпретация компьютерных программ» описана рекурсивная процедура вычисления показателей с использованием последовательного возведения в квадрат.
(define (fast-expt b n)
(cond ((= n 0)
1)
((even? n)
(square (fast-expt b (/ n 2))))
(else
(* b (fast-expt b (- n 1))))))
Теперь в упражнении 1.16:
Exercise 1.16: Design a procedure that evolves an iterative exponentiation process that uses successive squaring and uses a logarithmic number of steps, as does `fast-expt`. (Hint: Using the observation that(b(^n/2))^2 = (b(^2))^n/2
, сохраните вместе с показателем степени
n
и основаниемb
дополнительную переменную состоянияa
и определите преобразование состояния таким образом, чтобы произведениеab^n
не менялось от состояния к состоянию. В начале процессаa
принимается равным 1, а ответ дается значениемa
в конце процесса. В общем, метод определения инвариантной величины, которая остается неизменной от состояния к состоянию, является мощным способом подумать о разработке итерационных алгоритмов.)
Я потратил неделю и абсолютно не могу понять, как сделать эту итеративную процедуру, поэтому я сдался и стал искать решения. Все решения, которые я нашел, это:
(define (fast-expt a b n)
(cond ((= n 0)
a)
((even? n)
(fast-expt a (square b) (/ n 2)))
(else
(fast-expt (* a b) b (- n 1)))))
Теперь я могу понять
(fast-expt a (square b) (/ n 2)))
используя подсказку из книги, но мой мозг взорвался, когда n
нечетное. В рекурсивной процедуре я понял, почему
(* b (fast-expt b (- n 1))))))
работает. Но в итеративной процедуре все становится совершенно иначе,
(fast-expt (* a b) b (- n 1)))))
Он работает отлично, но я совершенно не понимаю, как самому прийти к этому решению. это кажется очень умным.
Может кто-нибудь объяснить, почему итеративное решение такое? И каков общий способ решения этих типов проблем?
Обновление 2021 г. В прошлом году я совершенно забыл об этом упражнении и решениях, которые видел. Я попытался решить ее и, наконец, решил самостоятельно, используя инвариант, представленный в упражнении, в качестве основы для преобразования переменных состояния. Я использовал принятый ответ, чтобы проверить свое решение. Спасибо, @Оскар Лопес.