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

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск

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

Применение[править | править вики-текст]

Длинная арифметика применяется в следующих областях:

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

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

Реализация в языках программирования[править | править вики-текст]

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

Большинство функциональных языков позволяют переключаться с обычной арифметики на длинную без необходимости изменения кода арифметических расчётов. Например, Erlang и Scheme всегда представляют точные числа длинными. В Standard ML реализации всех разновидностей целых чисел определяются на основании сигнатуры INTEGER, позволяя выбирать необходимую размерность,— в том числе присутствует модуль IntInf, реализующий целые числа произвольной точности; в реализации PolyML этот модуль используется по умолчанию.

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

Алгоритмы[править | править вики-текст]

Алгоритмы умножения[править | править вики-текст]

Для описания алгоритмов обычно используется следующее представление целых чисел. Выбирается основание ~~\beta > 1 . Тогда целое число длины n можно представить в виде:
~~A=a_{n-1} \cdot \beta^{n-1} + ... + a_1 \cdot \beta + a_0,
где  0 \le a_i \le \beta - 1 [1]

Базовый[править | править вики-текст]

Представляет собой алгоритм по школьному методу «в столбик». Занимает время O(n \cdot m), где n, m — размеры перемножаемых чисел.
Алгоритм может быть представлен в виде: [1] [2]

Algorithm 1 BasecaseMultiply
Input: A=\sum\nolimits_{i=0}^{m-1} a_i \beta^i, B=\sum\nolimits_{j=0}^{n-1} b_j \beta^j
Output: C=AB:=\sum\nolimits_{k=0}^{m+n-1} c_k \beta^k
1: C \gets A\cdot b_0
2: for j from 1 to n-1 do
3: ~~~~C \gets C + \beta^j(A \cdot b_j)
4: return~~C.

Умножение Карацубы[править | править вики-текст]

Метод умножения Карацубы относится к парадигме «разделяй и властвуй». Сложность вычисления алгоритма:

M(n)=O(n^{\log_23}),\quad\log_23=1{,}5849\ldots.

Данный алгоритм представляет собой простую реализацию[3] идеи разделения входных данных, которая стала базисной для нижеперечисленных алгоритмов. Идея заключается в разделении одной операции умножения над n-значными числами на три операции умножения над числами длины n/2 плюс O(n)[1].
Для перемножения двух чисел, превышающих длину машинного слова, алгоритм Карацубы вызывается рекурсивно до тех пор, пока эти числа не станут достаточно маленькими, чтобы их можно было перемножить непосредственно. Пример такого алгоритма:

Algorithm 2 KaratsubaMultiply
Input: A=\sum\nolimits_{i=0}^{n-1} a_i \beta^i, B=\sum\nolimits_{j=0}^{n-1} b_j \beta^j
Output: C=AB:=\sum\nolimits_{k=0}^{2n-1} c_k \beta^k
k \gets [n/2]
(A_0, B_0):=(A, B)mod \beta^k, (A_1, B_1):=(A, B)div \beta^k
s_A \gets sign(A_0-A_1), s_B \gets sign(B_0-B_1)
C_0 \gets KaratsubaMultiply(A_0,B_0)
C_1 \gets KaratsubaMultiply(A_1,B_1)
C_2 \gets KaratsubaMultiply(|A_0-A_1|,|B_0-B_1|)
return~C:=C_0+(C_0+C_1-s_As_BC_2) \beta^k + C_1 \beta^{2k}

Посчитаем ~x = 12345 \cdot 6789~:
12345 = 12 \cdot 1000 + 345
6789 = 6 \cdot 1000 + 789
Нужно вычислить три промежуточных коэффициента:
C_0 = 345 \cdot 789 = 272205
C_1 = 12 \cdot 6 = 72
C_2 = C_1 + C_0 - (345 - 12) \cdot (789 - 6) = 72 + 272205 -333 \cdot 783 = 11538
Результат:
x = C_1 \cdot 1000^2 + C_2 \cdot 1000 + C_0
x = 72 \cdot 1000^2 + 11538 \cdot 1000 + 272205 = 83810205

Алгоритм Тоома[править | править вики-текст]

Этот алгоритм является обобщением алгоритма Карацубы и работает быстрее. Для двух данных целых чисел A и B алгоритм Toom-a делит их на k меньших частей, длина каждой из которых равна длине машинного слова, и производит операции над этими частями. Сложность вычисления алгоритма: O(n^{ln(2k-1)/ln(k)}).

Алгоритм Тоома-3[править | править вики-текст]

Идея впервые была предложена А. Л. Тоомом в 1963 году[4], и заключается в разделении входных данных (множителей) на 3 равные части (для простоты все части считаем равными). Toom-3 сокращает число элементарных операций умножения с 9 до 5. Сложность алгоритма O(n^{1.465}).
Рассмотрим данный алгоритм на следующем примере. Пусть дано два числа Y и X. Пусть определены операции над числами, размер которых равен 1/3 от размеров исходных чисел (см. рисунок). Предположим также, что числа занимают равную память и делятся ровно на 3 части, в противном случае дополним оба числа нулями до необходимых размеров.

Разбиение входных чисел.jpg


Затем происходит отображение (параметризация) этих частей на полиномы 2 степени.
X(t) = x_2 \cdot t^2 + x_1 \cdot t + x_0,
Y(t) = y_2 \cdot t^2 + y_1 \cdot t + y_0,
Введем b, по определению такую, что значение многочленов X(b),~Y(b) соответственно равно входным числам x и y. Для битового представления чисел это число равно возведению 2 в степень, равную длине каждой из частей в битах. Также введем полином:
W(t)=X(t) \cdot Y(t), (1)
W(t) = w_4 \cdot t^4 + w_3 \cdot t^3 + w_2 \cdot t^2 + w_1 \cdot t + w_0,
После того как будут определены элементы w_i — коэффициенты многочлена~W(t)~, они будут использованы в целях получения w=W(b), так как ~x \cdot y=X(b) \cdot Y(b)=W(b)~. Размер коэффициентов ~w_i~ в 2 раза больше (по памяти), чем разбиение ~x_i~ или ~y_i~. Конечное число, равное произведению ~x \cdot y~ можно найти, складывая ~w_i~ со сдвигом, как показано на рисунке ниже.

Разбиение выходных чисел.jpg

Коэффициенты ~w_i~ могут быть вычислены следующим образом: w_4=x_2 \cdot y_2, w_3=x_2 \cdot y_1+x_1 \cdot y_2,~~ w_2=x_2 \cdot y_0+x_1 \cdot y_1+x_0 \cdot y_2 и так далее, но это потребует все 9 перемножений: x_i \cdot y_j для i, j=0,1,2, и будет эквивалентно простому перемножению.
Вместо этого был использован иной подход. ~X(t),Y(t)~ вычисляются в (1) в 5 точках при разных t.
В таблице, представленной ниже, приведены значения полиномов в равенстве (1)

t=0 x_0 \cdot y_0 W(0)~~~=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~w_0
t=1 (x_2+x_1+x_0) \cdot (y_2+y_1+y_0) W(1)~~~=~~~~w_4 + ~w_3 +  ~~w_2 +  ~w_1 + w_0
t=-1 (x_2-x_1+x_0) \cdot (y_2-y_1+y_0) W(-1)~=~~~~w_4 - ~w_3 + ~~w_2 - ~w_1 + w_0
t=2 (4x_2+2x_1+x_0) \cdot (4y_2+2y_1+y_0) W(2)~~~=~16w_4 + 8w_3 + 4w_2 + 2w_1 + w_0
t= \infty x_2 \cdot y_2 W(\infty)~~=~~~~w_4

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

Алгоритм Тоома-4[править | править вики-текст]

Сложность алгоритма O(n^{1.404}). Представляет собой 7 элементарных операций умножения. Toom-4 разделяет входные данные на 4 части.
По такому же принципу как и в Toom-3 строим два полинома:


X(t) = x3 \cdot t^3 + x2 \cdot t^2 + x1 \cdot t + x0,
Y(t) = y3 \cdot t^3 + y2 \cdot t^2 + y1 \cdot t + y0,

X(t) и Y(t) вычисляются в 7 разных точках, также вычисляется значение W(t) в этих точках.

t=0 x_0 \cdot y_0, откуда сразу получаем w_0
t=1/2 (x_3+2x_2+4x_1+8x_0) \cdot (y_3+2y_2+4y_1+8y_0)
t=-1/2 (-x_3+2x_2-4x_1+8x_0) \cdot (-y_3+2y_2-4y_1+8y_0)
t=1 (x_3+x_2+x_1+x_0) \cdot (y_3+y_2+y_1+y_0)
t=-1 (-x_3+x_2-x_1+x_0) \cdot (-y_3+y_2-y_1+y_0)
t=2 (8x_3+4x_2+2x_1+x_0) \cdot (8y_3+4y_2+2y_1+y_0)
t=\infty x_3 \cdot y_3, откуда сразу получаем w_6

Количество операций сложения и умножения для Toom-4 намного больше, чем для Toom-3. Но некоторые выражения встречаются по нескольку раз. Например, x_2+x_0 вычисляется для t=1 и для t=-1 [5].

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

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

Перемножение методом Фурье[править | править вики-текст]

Данный алгоритм перемножения используется для больших и очень больших чисел.[6]
Этот алгоритм перемножает два числа за время  O(n \cdot \log n) , где  n  — количество значащих цифр в перемножаемых числах (предполагая их равными). Создание приписывается Кули (Coolet) и Таки (Tukey) — 1965 г. Также есть предположения, что данный алгоритм был известен и раньше, но не имел большой важности до того как изобрели первые компьютеры. Вероятными кандидатами изобретения данного алгоритма также называют Рунг (Runge) и Кёниг (Konig) — 1924 г., а также Гаусса — 1805 г.
Пусть имеется число, представим его в виде многочлена, как мы делали ранее. Назовем этот многочлен A(x). Также введем дискретное Фурье преобразование многочлена как вектор, с координатами   	\left (b_1, b_2, b_3, b_4, \dots b_{n-1}\right ). Где b[i] определены как w^n[i] — комплексный корень n-ой степени из 1, не равный 1. Дело в том, что комплексный корень из 1 определен с точностью до фазового множителя, количество этих корней — n. Фурье преобразование применено для того, чтобы свертку коэффициентов многочленов A и B: (A(x) \cdot B(x)) — заменить на произведение их Фурье образов.
F(A(x)  \cdot  B(x)) = F (A)  \cdot  F (B)
 A(x)  \cdot  B(x) = F^{-1} (F (A)  \cdot  F (B)),
где под умножением F (A)  \cdot  F (B) подразумевается скалярное произведение векторов.
Предположим, что n есть степень двойки.
Нахождение F(A) производится рекурсивным методом (разделяй и властвуй). Идея заключается в разбиении исходного многочлена A (x) = a_0x_0 + a_1x_1 + ... + a_{n-1}x_{n-1} на два многочлена,
A0 (x) = a_0x_0 + a_2x_1 + a_4x_2 + \dots + a_{n-2}x_{\frac{n-2}{2}}
A1 (x) = a_1x_0 + a_3x_1 + a_5x_2 + \dots + a_{n-1}x_{\frac{n-2}{2}}
Тогда A(x) = A0 (x^2) + x  \cdot  A1 (x^2).
Заметим, что среди всех чисел \left (w^n_i\right )^2 (0 \leq i < n), только \frac{n}{2} различных. Поэтому, ДПФ A0 и A1 будут \frac{n}{2}-элементными. А так как ДПФ A0 и A1 состоит из \frac{n}{2} элементов, то комплексным корнем из 1 там будет корень степени \frac{n}{2}.
Значит, A(w^n_k) = A0(w^n_{2k}) + w^n_k  \cdot  A1(w^n_{2k}) = A0(w^\frac{n}{2}_k) + w^n_k  \cdot  A1(w^\frac{n}{2}_k), где 0 \leq k < n / 2 и
A(w^n_{k+\frac{n}{2}}) = A0(w^n_{2 \cdot {k+\frac{n}{2}}}) + w^n_{k+\frac{n}{2}}  \cdot  A1(w^n_{2 \cdot {k+\frac{n}{2}}}) = A0(w^{n/2}_{k+\frac{n}{2}}) + w^n_{k+\frac{n}{2}}  \cdot  A1(w^\frac{n}{2}_{k+\frac{n}{2}}) = A0(w^\frac{n}{2}_k) - w^n_k  \cdot  A1(w^\frac{n}{2}_k).
Мы использовали свойства комплексных чисел: различных корней степени n всего  n. w^n_{k+\frac{n}{2}}  = w^n_k  \cdot  e^{i \cdot \frac{2\pi}{n}  \cdot  \frac{n}{2}} = w^n_k  \cdot  e^{i \cdot \pi} = - w^n_k.

Получаем рекурсивный алгоритм:
ДПФ одного элемента равно этому элементу
для нахождения ДПФ A разбиваем коэффициенты A на чётные и нечётные, получаем два многочлена A0 и A1, находим ДПФ для них, находим ДПФ A:
b_k = b^0_k + w^n_k  \cdot  b^1_k
b_{k + \frac{n}{2}} = b^0_k - w^n_k  \cdot  b^1_k
для 0 \leq k < n / 2.
Существует доказательство следующего утверждения: Обратное ДПФ находится аналогично прямому ДПФ, за исключением того, что в качестве точек берутся точки, симметричные относительно вещественной оси, вместо тех, что использовались в прямом ДПФ преобразовании. Также необходимо все коэффициенты многочлена поделить на n

Алгоритмы извлечения корня[править | править вики-текст]

Квадратный корень[править | править вики-текст]

На данный момент это самый известный метод, чтобы посчитать квадратный корень n-значного числа. Этот алгоритм использует Быстрое преобразование Фурье и Метод Ньютона со сложностью 5M(n). .[7]

Представленный алгоритм основан на делении Бурникеля - Циглера (Burnikel-Ziegler) Карацубы. Имея целое число n, наш алгоритм подсчитывает одновременно его целый квадратный корень  s = \lfloor \sqrt{n} \rfloor и соответствующий остаток, который равен  r = n-s^2 . Это не является асимптотически оптимальным, но очень эффективно на практике со сложностью порядка  \frac{3}{2}K(n) операций, где K(n)- это количество операций, необходимых чтобы умножить два n-разрядных числа, используя алгоритм Карацубы (Karatsuba). Причина этой низкой сложности в красивом делении Карацубы (Karatsuba), недавно открытым Бурникелем и Циглером (Burnikel and Ziegler), а также в осторожном обращении с остатками, которое избегает ненужных вычислений. Алгоритм SqrtRem использует со 2n-разрядным входом ограничено  \frac{3}{2}K(n)+O(nlogn) , где K(n)-число операций, необходимых для умножения 2n-разрядных чисел, используя алгоритм Карацубы.

Algorithm SqrtRem  (n = a_{3}b_{3}+a_{2}b_{2}+a_{1}b+a_{0})
~ Input: <math> 0 \le a_{i} \le b ~ with~ a_{3} \ge b/4
 Output: (s,r)~ such~ that~ s^2 \le n = s^2 + r < (s+1)^2
 (s', r') \leftarrow SqrtRem(a_{3}b+a_{2})
 (q,u) \leftarrow DivRem(r'b+a_{1},2s')
 s \leftarrow ub+a_{0}-q^2
 if ~r < 0 ~then~
 r \leftarrow r+2s-1
 s \leftarrow s-1
 return (s,r)


Алгоритмы преобразования системы счисления[править | править вики-текст]


Предположим, что выполняется преобразование из системы счисления по осно­ванию b в систему счисления по основанию В. [8]

Способы преобразования целых чисел[править | править вики-текст]


Метод 1 (Деление на В с использованием представления чисел в формате по основанию b). Для заданного целого числа и можно
получить представление в формате по основанию В вида  ( ... U_{2}U_{1}U_{0})_{B} , выполняя

 U_{0} = u modB ,     U_{1}= \left \lfloor \frac{u}{B} \right \rfloor modB  ,   U_{2} = \left \lfloor \left \lfloor \frac{u}{B} \right \rfloor \right \rfloor  modB ,до тех пор, пока не окажется  \left \lfloor {...} { \left \lfloor { \left \lfloor \frac{u}{B} \right \rfloor }  \right \rfloor }  {.../B}  \right \rfloor   =0.


Метод 2 (Умножение на В с использованием представления чисел в формате по основанию b). Если представление числа и по основанию b имеет вид  (u_{m}{...}u_{1}u_{0})_{b} , то можно, воспользовавшись арифметическими операциями с числами, которые представлены в формате по основанию В, получить полином  u_{m}b^{m}+{...}+u_{1}b+u_{m}u_{0}=u в виде
(( ...  ( u_{m}b + u_{m-1}){b} + ...)  b +  u_{1}b + u_{0} .


Способы преобразования целых чисел[править | править вики-текст]


Метод 1 (a) (Умножение на b с использованием представления чисел в формате по основанию В). Для данного дробного числа и можно вычислить значения разрядов  (.U_{-1}U_{-2} ... )_{B} его представления по основанию В следующим образом:
 U_{-1}= \left \lfloor \ {uB} \right \rfloor ,  U_{-2}  {=} \left \lfloor \ {{uB}B}\right \rfloor ,  U_{-3}= \left \lfloor \ {((uB)B)B} \right \rfloor ,... где {х} означает xmod1 = х-  \left \lfloor \ {x} \right \rfloor . Чтобы округлить результат до М разрядов, вычисления можно прервать после получения  U_{M} , причем если {...{{uВ}В}...В} больше 1/2, то значение  U_{M} следует увеличить на единицу. (Заметим, однако, что эта операция может привести к необходимости выполнения переносов, которые должны быть при помощи арифметических операций по основанию В включены в результат. Было бы проще перед началом вычислений прибавить к исходному числу u константу  1/2 B^{-M} , но это может привести к неправильному результату, если в компьютере число  1/2 B^{-M} не может быть точно представлено в формате по основанию b. Заметим также, что возможно округление результата до  (1.00...0)^B , если  b^{m}  \geq  2B^{M} ).
Метод 2 (a) (Умножение на В с использованием представления чисел в формате по основанию b). Если представление числа и по основанию b имеет вид  (u_{m}{...}u_{1}u_{0})_{b} , то можно, воспользовавшись арифметическими операциями с числами, которые представлены в формате по основанию В, получить полином  u_{m}b^{m}+{...}+u_{1}b+u_{m}u_{0}=u в виде
(( ...  ( u_{m}b + u_{m-1}){b} + ...)  b +  u_{1}b + u_{0} .

Способы преобразования дробных чисел[править | править вики-текст]


Метод 1 (b) (Умножение на b с использованием представления чисел в формате по основанию В). Для данного дробного числа u можно вычислить значения разрядов  (0.U_{-1}U_{-2} ... )_{B} его представления по основанию В следующим образом:
 U_{-1}= \left \lfloor \ {uB} \right \rfloor ,  U_{-2}  {=} \left \lfloor \ {{uB}B}\right \rfloor ,  U_{-3}= \left \lfloor \ {((uB)B)B} \right \rfloor ,... где {х} означает xmod1 = х-  \left \lfloor \ {x} \right \rfloor . Чтобы округлить результат до М разрядов, вычисления можно прервать после получения  U_{M} , причем если {...{{uВ}В}...В} больше 1/2, то значение  U_{M} следует увеличить на единицу. (Заметим, однако, что эта операция может привести к необходимости выполнения переносов, которые должны быть при помощи арифметических операций по основанию В включены в результат. Было бы проще перед началом вычислений прибавить к исходному числу u константу  1/2 B^{-M} , но это может привести к неправильному результату, если в компьютере число  1/2 B^{-M} не может быть точно представлено в формате по основанию b. Заметим также, что возможно округление результата до  (1.00...0)^B , если  b^{m}  \geq  2B^{M} ).


Метод 2 (b)(Деление на b с использованием представления чисел в формате по основанию В). Если число u представлено по основанию b в виде  (0.u_{-1}u_{-2} ... u_{-m})_{b} , то можно, используя арифметические операции по основанию В, вычислить  u_{-1}b^{-1}+u_{-2}b^{-2}+{...}+u_{-m}b{-m} в виде
 ((... (u_{-m}/b + u_{1-m})/b + ... + u_{-2})/b + u_{-1})/b . Необходимо внимательно следить за погрешностями, возникающими при усечениях или округлениях во время выполнения операции деления на b; они, как правило, незначительны, но это бывает не всегда.

Преобразование с многократной точностью[править | править вики-текст]


Начинать преобразование очень длинных чисел удобнее всего с преобразования блоков разрядов, операции с которыми можно выполнять с однократной точностью. Затем следует объединить эти блоки, пользуясь простыми способами, которые специфичны для многократной точности. Например, пусть 10n-наивысшая степень 10, меньшая, чем размер машинного слова. Тогда:
а) чтобы преобразовать целое "Число с многократной точностью из двоичного фор­мата в десятичный, необходимо многократно разделить его на 10n (выполняя таким образом преобразование из двоичной системы счисления в десятичную с основанием 10n по методу 1, а); при помощи операций с однократной точностью получим n десятичных разрядов для каждой единицы представления в системе счисления с основанием 10n;
b) чтобы преобразовать дробную "Часть числа с многократной точностью из дво­ичного формата в десятичный, поступим подобным образом, умножив его на  10^n : (т.е. использовав метод 2, а, где В= 10n);
с) чтобы преобразовать целое число с многократной точностью из десятичной системы счисления в двоичную, преобразуем сначала блоки по n разрядов; затем для перехода из системы счисления с основанием 10n в двоичный формат используем метод 1, b;
d) для преобразования дробной части с многократной точностью из представления в десятичном формате в двоичный сначала выполним преобразование в систему с основанием 10n, как и в процедуре (с), а затем используем метод 2, b.



Алгоритмы деления[править | править вики-текст]

Чтобы разделить n-битовое число u на n - битовое число v, можно сначала найти n-битовое приближение к числу 1/v, затем умножить его на u, что даст приближение   \hat{q} к  u/v , И наконец выполнить еще одно умножение для внесения небольшой коррекции в  \hat{q} , чтобы убедиться, что выполняется неравенство  0 \le u-qv < v . Исходя из сказанного, достаточно иметь эффективный алгоритм, который формировал бы по заданному n-битовому числу приближенное значение числа, обратного n-битовому числу. Далее применить алгоритм умножения n-битовых чисел. [9]


Алгоритм R (Получение обратной величины с высокой точностью) Пусть число v имеет двоичное представление  v=(0.v_{1}v_{2}v_{3})_{2} , где  v_{1}=1 . Этот алгоритм вычисляет приближение z числа  1/v , такое, что
 |z-1/v| \le 2^{-n} .
R1(Начальное приближение) Присвоить  z \leftarrow \frac{1}{4} \left \lfloor \frac{32}{(4v_{1}+2v_{2}+v_{3})} \right \rfloor и  k \leftarrow 0 .
R2 (Итерация по Ньютону) Здесь имеем число z в двоичном виде  (xx.xx...x)_{2} с  2^k+1 знаками после разеляющей точки и  z \le 2 . При помощи программы быстрого умножения точно вычислить  z^2=(xx.xx...x)_{2} . После этого точно вычислить  V_{k}z^2 , где  V_{k}= (0.v_{1}v_{2}...v_{2^{k+1}+3})_{2} . Затем присвоить  z \leftarrow 2z-V_{k}z^2+r , где  r , удовлетворяющее неравенству  0 \le r <2^{-2^{k+1}-1} , прибавляется при необходимости для округления  z , чтобы  z было кратным  2^{-2^{k+1}-1} . И наконец присвоить  k \leftarrow k+1 .
R3 Если   2^k<n , то вернуться к шагу R2; в противном случае выполнение алгоритма заканчивается.


Другие алгоритмы[править | править вики-текст]

Примечания[править | править вики-текст]

  1. 1 2 3 Richard P. Brent and Paul Zimmermann, Modern Computer Arithmetic
  2. Donald E. Knuth «The Art of Computer Programming», Секция 4.3.1
  3. Donald E. Knuth «The Art of Computer Programming», Секция 4.3.3, часть А
  4. Доклады академии наук СССР 150 (1963), 496—498
  5. Toom 4-Way Multiplication — GNU MP 5.1.3
  6. Donald E. Knuth «The Art of Computer Programming», Секция 4.3.3, часть С
  7. Paul Zimmermann. Karatsuba Square Root. [Research Report] RR-3805, 1999, pp.8. <inria-00072854>
  8. Donald E. Knuth «The Art of Computer Programming», том 2, Секция 4.4
  9. Donald E. Knuth «The Art of Computer Programming», том 2, Секция 4.3.3

Литература[править | править вики-текст]

  • Donald E. Knuth, «The Art of Computer Programming», volume 2, «Seminumerical Algorithms», 3rd edition, Addison-Wesley, 1998
  • Dan Zuras, «On Squaring and Multiplying Large Integers», ARITH-11: IEEE Symposium on Computer Arithmetic, 1993, pp. 260 to 271.
  • ДАН СССР 150 (1963), 496—498
  • Richard P. Brent and Paul Zimmermann, Modern Computer Arithmetic
  • Электронные средства и системы управления : Материалы докладов Международной научно-практической конференции (13-16 октября 2010 г.). — Томск: В-Спектр, 2011: В 2 ч. — Ч. 2. — 178 с. ISBN 978-5-91191-223-6, С.123-129