Длинная арифметика

Материал из Википедии — свободной энциклопедии
Это старая версия этой страницы, сохранённая 188.134.44.15 (обсуждение) в 07:57, 31 марта 2013 (Перемножение методом Фурье). Она может серьёзно отличаться от текущей версии.
Перейти к навигации Перейти к поиску

Длинная арифметика — в вычислительной технике операции (сложение, вычитание, умножение, деление, возведение в степень, элементарные функции) над числами, разрядность которых превышает длину машинного слова данной вычислительной машины. Эти операции реализуются не аппаратно, а программно, используя базовые аппаратные средства работы с числами меньших порядков. Частный случай — арифметика произвольной точности — относится к арифметике, в которой длина чисел ограничена только объёмом доступной памяти.

Основные потребители

  • Компьютеры низкой разрядности, микроконтроллеры. Например, микроконтроллеры серии AVR имеют 8-битный регистр и 10-битный АЦП — так что при обработке информации с АЦП без длинной арифметики не обойтись.
  • Криптография. Большинство систем шифрования данных, а также систем цифрофой подписи данных используют целочисленную арифметику по модулю m, где m — очень большое положительное натуральное чисто, не обязательно простое. Для примера RSA[1], Rabin[2] или Эль Гамаль[3] требуют наличие эффективных методов для операций перемножения и возведения в степень для чисел, имеющих порядки 10309Шаблон:-1
  • Математическое и финансовое ПО, требующее, чтобы результат вычисления на компьютере совпал до последнего разряда с результатом вычисления на бумаге. В частности, калькулятор Windows (начиная с Windows 95). Калькулятор Windows Vista и далее проводит четыре арифметических действия с намного большей точностью, чем позволяет процессор x86.
  • Одна из излюбленных тем спортивного программирования. С распространением стандартных библиотек для работы с длинными числами постепенно сходит на нет.

Необходимые аппаратные средства для работы с длинной арифметикой

Строго говоря, для реализации арифметики произвольной точности от процессора требуется лишь косвенная адресация; в арифметике фиксированной точности можно обойтись даже без неё. Тем не менее, определённые функции процессора ускоряют длинную арифметику, одновременно упрощая её программирование.

Реализация в языках программирования

Языки программирования имеют встроенные типы данных, размер которых, в основном, не превышает 64 бита (около 1019). Десятичная длинная арифметика была реализована в языке программирования АЛМИР-65 на ЭВМ МИР-1 и в языке программирования АНАЛИТИК на ЭВМ МИР-2. Для работы с большими числами, однако, существует довольно много готовых оптимизированных библиотек для длинной арифметики.

Встроенные библиотеки работы с большими числами есть в Python и Java.

Алгоритмы

Алгоритмы умножения

Базовый

Представляет собой алгоритм по школьному методу «в столбик». Занимает время O(N*M), где N, M — размеры перемножаемых чисел. Его алгоритм подробно описан в книге [1]. Секция 4.3.1.

Этот алгоритм также описан в [1]. Секция 4.3.3, часть А[4]. Данный алгоритм представляет собой наиболее простую реализацию идеи разделения входных данных, которая стала базисной для нижеперечисленных алгоритмов.

Toom 3-Way

Идея впервые была предложена А. Л. Тоомом в [3], и заключается в разделении входных данных (множителей) на 3 равные части(для простоты все части считаем равными).
Рассмотрим данный алгоритм на следующем примере. Пусть дано два числа Y и X. Пусть определены операции над числами, размер которых равен 1/3 от размеров исходных чисел (см. рисунок). (предположим также, что числа занимают равную память и делятся ровно на 3 части, в противном случае дополним оба числа нулями до необходимых размеров.

Затем происходит отображение (параметризация) этих частей на полиномы 2 степени.

Введем , по определению такую, что значение многочленов соответственно равно входным числам и . Для битового представления чисел это число равно возведению 2 в степень, равную длине каждой из частей в битах.

Также введем полином:
(1).

После того как будут определены элементы  — коэффициенты многочлена, они будут использованы в целях получения , так как . Размер коэффициентов в 2 раза больше (по памяти), чем разбиение или . Конечное число, равное произведению можно найти, складывая со сдвигом, как показано на рисунке ниже.

Коэффициенты могут быть вычислены следующим образом: и так далее, но это потребует все 9 перемножений: для i, j=0,1,2, и будет эквивалентен простому перемножению. Вместо этого был использован иной подход. вычисляются в (1) в 5 точках при разных .
В таблице, представленной ниже, приведены значения полиномов в равенстве (1)





Параметр t=inf условный. Он означает банальное равенство коэффициентов при , тем самым мы полум значение сразу. Данная система линейна относительно 5 неизвестных. При её разрешении мы получаем неизвестные . Далее получаем значение многочлена, как было описано выше.

Toom 4-Way

Алгоритм Тоом-а для произвольного разбиения

Алгоритм Тоома для разделения входных чисел на n операндов эквивалентен описанному выше. В общем случае разделение двух одинаково длинных операндов на r частей приводит к вычислению значений в 2*r-1 точках. В качестве точек для решения системы, обычно берут 0, inf, +1, −1 and ±2^i, ±2^-i.

Перемножение методом Фурье

Данный алгоритм перемножения используется для больших и очень больших чисел. Описание данного алгоритма можно найти в различных источниках, в частности [1] секция 4.3.3 часть С[5], или Lipson глава 9. Далее приводится описание алгоритма.
Данный вид алгоритма перемножения двух чисел, за время , где  — количество значащих цифр в перемножаемых числах (предполагая их равными), приписывается Кули (Coolet) и Таки (Tukey) — 1965 г. Также есть предположения, что данный алгоритм был известен и раньше, но не имел большой важности до того как изобрели первые компьютеры. Вероятными кандидатами изобретения данного алгоритма также называют Рунг (Runge) и Кёниг (Konig) — 1924 г., а также Гаусса — 1805 г.
Пусть имеется число, представим его в виде многочлена, как мы делали ранее. Назовем этот многочлен . Также введем дискретное Фурье [6]преобразование многочлена как вектор [7], с координатами . Где определены как  — комплексный корень -ой степени из 1, не равный 1[8]. Дело в том, что комплексный корень из 1 определен с точностью до фазового множителя, количество этих корней — . [9] Фурье преобразование применено для того, чтобы свертку[10] коэффициентов многочленов А и В:  — заменить на произведение их Фурье образов.

,
где под умножением F (A) * F (B) подразумевается скалярное произведение векторов.
Предположим, что n есть степень двойки.
Нахождение F(A) производится рекурсивным методом (разделяй и властвуй). Идея заключается в разбиении исходного многочлена на два многочлена,


Тогда .
Заметим, что среди всех чисел (0 <= i < ), только различных. Поэтому, ДПФ и будут -элементными. А так как ДПФ A0 и A1 состоит из элементов, то комплексным корнем из 1 там будет корень степени .
Значит, , где 0 <= k < n / 2 и
.
Мы использовали свойства комплексных чисел: различных корней степени n всего n. .

Получаем рекурсивный алгоритм:
ДПФ одного элемента равно этому элементу
для нахождения ДПФ A разбиваем коэффициенты A на чётные и нечётные, получаем два многочлена A0 и A1, находим ДПФ для них, находим ДПФ A:


для 0 <= k < n / 2.
Существует доказательство следующего утверждения: Обратное ДПФ находится аналогично прямому ДПФ, за исключением того, что в качестве точек берутся точки, симметричные относительно вещественной оси, вместо тех, что использовались в прямом ДПФ преобразовании. Также необходимо все коэффициенты многочлена поделить на n

Алгоритмы деления

Алгоритмы возведения в степень

Алгоритмы извлечения корня

Алгоритмы преобразования системы счисления

Другие алгоритмы

Литература

  1. Donald E. Knuth, «The Art of Computer Programming», volume 2, «Seminumerical Algo-rithms», 3rd edition, Addison-Wesley, 1998Искусство программирования
  2. Dan Zuras, «On Squaring and Multiplying Large Integers», ARITH-11: IEEE Symposium on Computer Arithmetic, 1993, pp. 260 to 271.
  3. ДАН СССР 150 (1963), 496—498