Раздел 1.2.6 SICP дает следующую процедуру:
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(remainder (square (expmod base (/ exp 2) m))
m))
(else
(remainder (* base (expmod base (- exp 1) m))
m))))
Авторы утверждают, что он вычисляет экспоненту числа по модулю другого числа. Например, (expmod 5 3 n)
должен возвращать (5^3) по модулю n.
Однако с математической точки зрения я просто не понимаю, как это работает. Согласно сноске 46, предполагается использовать свойство, состоящее в том, что для любых положительных целых чисел a, b и n (ab) mod n = [(a mod n)(b mod n)] mod n, но мне не удается посмотреть, как он на самом деле использует его. Рассмотрим (expmod 5 3 3)
:
- Сначала мы вызываем
(expmod 5 3 3)
. Математически это означает, что мы запрашиваем (5^3) по модулю 3. - Поскольку второй параметр нечетный, мы вычисляем
(remainder (* 5 (expmod 5 (- 3 1) 3)) 3)
, т. е.(remainder (* 5 (expmod 5 2 3)) 3)
. Математически это [5 * [(5^2) по модулю 3]] по модулю 3. Поскольку к начальному числу 5 в этом выражении не присоединен модуль по модулю 3, это выражение не находится в (ab ) mod n = [(a mod n)(b mod n)] mod n form, поэтому не удается использовать предполагаемое свойство.
Итак, учитывая, что это, похоже, не использует предполагаемое свойство, почему этот алгоритм работает? Какое свойство модульной арифметики я упустил из виду?