Русская Википедия:Алгоритмы быстрого возведения в степень
Алгоритмы быстрого возведения в степень (дихотомический алгоритм возведения в степень, бинарный алгоритм возведения в степень) — алгоритмы, предназначенные для возведения числа <math>x</math> в натуральную степень <math>n</math> за меньшее число умножений, чем это требуется в определении степени[1]. Многие из этих алгоритмов основаны на том, что для возведения числа <math>x</math> в степень <math>n</math> не обязательно перемножать число <math>x</math> на само себя <math>n</math> раз, а можно перемножать уже вычисленные степени. В частности, если <math>n=2^k</math> степень двойки, то для возведения в степень <math>n</math> достаточно число возвести в квадрат <math>k</math> раз, затратив при этом <math>k</math> умножений вместо <math>2^k</math>. Например, чтобы возвести число <math>x</math> в восьмую степень, вместо выполнения семи умножений <math>x\cdot x\cdot x\cdot x\cdot x\cdot x\cdot x\cdot x</math> можно возвести число в квадрат (<math>x^2=x\cdot x</math>), потом результат возвести ещё раз в квадрат и получить четвёртую степень (<math>x^4=x^2\cdot x^2</math>), и наконец результат ещё раз возвести в квадрат и получить ответ (<math>x^8=x^4\cdot x^4</math>).
Кроме того, некоторые алгоритмы для дальнейшей оптимизации используют тот факт, что операция возведения в квадрат быстрее операции умножения за счёт того, что при возведении в квадрат цифры в сомножителе повторяютсяШаблон:Sfn.
Бинарный алгоритм возведения в степень был впервые предложен в XV веке персидским математиком Аль-КашиШаблон:Sfn.
Данные алгоритмы не всегда оптимальны. Например, при использовании схемы «слева направо» быстрое возведение в степень n = 15 потребует выполнения трёх операций умножения и трёх операций возведения в квадрат, хотя возведение в 15-ю степень можно выполнить и за 3 умножения и 2 возведения в квадратШаблон:Sfn. Оптимальное возведение в степень соответствует построению кратчайшей аддитивной цепочки.
Описание
Основным алгоритмом быстрого возведения в степень является схема «слева направо». Она получила своё название вследствие того, что биты показателя степени просматриваются слева направо, то есть от старшего к младшемуШаблон:Sfn.
Пусть
- <math>n=(\overline {m_{k}m_{k-1}...m_{1}m_{0}})_2</math> — двоичное представление степени n, то есть,
- <math>n=m_{k} \cdot 2^{k}+m_{k-1} \cdot 2^{k-1}+\dots+m_{1} \cdot 2+m_{0},</math>
где <math>m_{k}=1, m_{i} \in \{ 0,1 \}</math>. Тогда
- <math>x^{n}=x^{((\dots((m_{k} \cdot 2+m_{k-1}) \cdot 2+m_{k-2}) \cdot 2+\dots) \cdot 2+m_{1}) \cdot 2 + m_{0}}=((\dots(((x^{m_{k}})^{2} \cdot x^{m_{k-1}})^{2}\dots)^{2} \cdot x^{m_{1}})^2 \cdot x^{m_{0}}</math>Шаблон:Sfn.
Последовательность действий при использовании данной схемы можно описать так:
- Представить показатель степени n в двоичном виде
- Если <math>m_i</math> = 1, то текущий результат возводится в квадрат и затем умножается на x. Если <math>m_i</math> = 0, то текущий результат просто возводится в квадратШаблон:Sfn. Индекс i изменяется от k-1 до 0Шаблон:Sfn.
Таким образом, алгоритм быстрого возведения в степень сводится к мультипликативному аналогу схемы ГорнераШаблон:Sfn:
- <math>\begin{Bmatrix} s_1=x \\ s_{i+1}=s_i^2 \cdot x^{m_{k-i}} \\ i=1,2,\dots,k \end{Bmatrix}.</math>
Обобщения
Пусть пара (S, *) — полугруппа, тогда мы можем назвать операцию * умножением и определить операцию возведения в натуральную степень:
- <math>a^n=\left\{ \begin{array}{ll} a & n = 1 \\ a * \left(a^{n-1}\right) & n > 1 \end{array} \right.</math>
Тогда для вычисления значений an в любой полугруппе (в абелевой группе в частности) можно использовать алгоритмы быстрого возведения в степеньШаблон:Sfn.
Примеры решения задач
Применяя алгоритм, вычислим 2113:
- <math>13_{10} = 1101_2</math>
- <math>m_3=1, m_2=1, m_1=0, m_0=1</math>
- <math>
\begin{align} 21^{13} & = ((( 1 \cdot 21^{m_3} )^2 \cdot 21^{m_2} )^2 \cdot 21^{m_1}) ^2 \cdot 21^{m_0} \\ & = ((( 1 \cdot 21^1 )^2 \cdot 21^1 )^2 \cdot 21^0) ^2 \cdot 21^1 \\ & = ((( 1 \cdot 21 )^2 \cdot 21 )^2 \cdot 1) ^2 \cdot 21 \\ & = ((21^2 \cdot 21)^2)^2 \cdot 21 \\ & = ((441\cdot21)^2)^2\cdot21 \\ & = 85766121^2\cdot21 \\ & = 154472377739119461 \end{align} </math>
Схема «справа налево»
В данной схеме, в отличие от схемы «слева направо», биты показателя степени просматриваются от младшего к старшемуШаблон:Sfn.
Последовательность действий при реализации данного алгоритма.
- Представить показатель степени n в двоичном виде.
- Положить вспомогательную переменную z равной числу x.
- Если <math>m_i=1</math>, то текущий результат умножается на z, а само число z возводится в квадрат. Если <math>m_i</math> = 0, то требуется только возвести z в квадратШаблон:Sfn. При этом индекс i, в отличие от схемы слева направо, изменяется от 0 до k-1 включительноШаблон:Sfn.
Данная схема содержит столько же умножений и возведений в квадрат, сколько и схема «слева направо». Однако несмотря на это, схема «слева направо» выгоднее схемы «справа налево», особенно в случае, если показатель степени содержит много единиц. Дело в том, что в схеме слева направо в операции result = result · x содержится постоянный множитель x. А для небольших x (что нередко бывает в тестах простоты) умножение будет быстрым. К примеру, для x = 2 мы можем операцию умножения заменить операцией сложенияШаблон:Sfn.
Математическое обоснование работы данного алгоритма можно представить следующей формулой:
- <math>d = a^n = </math>
- <math>= a^{\sum_{i=0}^k m_i\cdot 2^i} = </math>
- <math>= a^{m_0}\cdot a^{2m_1}\cdot a^{2^2*m_2}\cdot ... \cdot a^{2^k*m_k}= </math>
- <math>= a^{m_0}\cdot (a^2)^{m_1}\cdot (a^{2^2})^{m_2}\cdot ... \cdot (a^{2^k})^{m_k}= </math>
- <math> = \prod_{i=0}^k {(a^{2^{i}})^{m_i}}</math>Шаблон:Sfn.
Пример. Посчитаем с помощью схемы возведения в степень «справа налево» значение 2113.
i | 0 | 1 | 2 | 3 |
---|---|---|---|---|
<math>a^{2^{i}}</math> | 21 | 441 | 194 481 | 37 822 859 361 |
<math>m_i</math> | 1 | 0 | 1 | 1 |
- 21 · 194 481 = 4084 101
- 4084 101 · 37 822 859 361 = 154 472 377 739 119 461
Вычислительная сложность
И для схемы «слева направо», и для схемы «справа налево» количество операций возведения в квадрат одинаково и равно k, где k — длина показателя степени n в битах, <math>k \sim \ln{n}</math>. Количество же требуемых операций умножения равно весу Хэмминга, то есть количеству ненулевых элементов в двоичной записи числа n. В среднем требуется <math>\frac{1}{2}\cdot\ln{n}</math> операций умноженияШаблон:Sfn.
Например, для возведения числа в сотую степень этим алгоритмом потребуется всего лишь 8 операций умножения и возведения в квадратШаблон:Sfn.
Для сравнения, при стандартном способе возведения в степень требуется <math>n-1</math> операция умножения, то есть количество операций может быть оценено как <math> O(n) </math>Шаблон:Sfn.
Оптимизация алгоритма
Как правило, операция возведения в квадрат выполняется быстрее операции умножения. Метод окон позволяет сократить количество операций умножения и, следовательно, сделать алгоритм возведения в степень более оптимальнымШаблон:Sfn.
Окно фактически представляет собой основание системы счисленияШаблон:Sfn. Пусть w — ширина окна, то есть за один раз учитывается w знаков показателя.
Рассмотрим метод окна.
- Для <math>i = \overline {0, 2^w-1}</math> заранее вычисляется xi
- Показатель степени представляется в следующем виде: <math>n = \sum_{i=0}^{k/w}{n_i\cdot2^{i\cdot w}}</math>, где <math>n_i \in {(0, 1, ..., 2^w-1)}</math>
- Пусть y — переменная, в которой будет вычислен конечный результат. Положим <math>y=x^{n_{k/w}}</math>.
- Для всех i = k/w — 1, k/w — 2, …, 0 выполнить следующие действия:
- <math>y = y^{2^w}</math>
- <math>y = y\cdot x^{n_i}</math>Шаблон:Sfn.
В данном алгоритме требуется k возведений в квадрат, но число умножений в среднем сокращается до k/wШаблон:Sfn.
Ещё более эффективным является метод скользящего окна. Он заключается в том, что ширина окна во время выполнения процесса может изменяться:
- Показатель степени представляется в виде <math>n = \sum_{i=0}^{l}{n_i\cdot2^{e_i}}</math>, где <math>n_i \in {(1, 3, 5, ..., 2^w-1)}</math>, а ei+1 — ei ≥ w.
- Для <math>i = (1, 3, 5, ..., 2^w-1)</math> вычисляется xi. Далее будем обозначать xi как xi.
- Пусть y — переменная, в которой будет вычислен конечный результат. Положим <math>y=x^{n_{l}}</math>.
- Для всех i = l — 1, l — 2, …, 0 выполнить следующие действия:
- Для всех j от 0 до ei+1 — ei — 1 y возвести в квадрат
- <math>j = m_i</math>
- <math>y = y\cdot x_j</math>
- Для всех j от 0 до e0 — 1 y возвести в квадратШаблон:Sfn.
Количество операций возведения в степень в данном алгоритме такое же, как и в методе окна, а вот количество операций умножений сократилось до l, то есть до <math>\frac{k}{w+1}</math> в среднемШаблон:Sfn.
Для примера возведём методом скользящего окна число x в степень 215. Ширина окна w = 3.
- 215 = 27 + 5 · 24 + 7
- y = 1
- y = y · x = x
- y 3 раза возводится в квадрат, так как на данном шаге e2 — e1 −1 = 7 — 4 — 1 = 2, а отсчёт ведётся с нуля, то есть y = y8 = x8
- y = y · x5 = x13
- y 4 раза возводится в квадрат, так как на данном шаге e1 — e0 −1 = 4 — 0 — 1 = 3, то есть y = y16= x208
- y = y · x7 = x215
Применение
Алгоритм быстрого возведения в степень получил широкое распространение в криптосистемах с открытым ключом. В частности, алгоритм применяется в протоколе RSA, схеме Эль-Гамаля и других криптографических алгоритмахШаблон:Sfn.
См. также
Примечания
Литература
- Шаблон:Книга
- Шаблон:Source
- Шаблон:Книга
- Шаблон:Source
- Шаблон:Книга
- Шаблон:Source
- Шаблон:Source
- Шаблон:Source
Шаблон:ВС Шаблон:Добротная статья