Арифметика чисел большой разрядности
Размерность обрабатываемых в вычислительных машинах чисел обычно ограничивается размерностью машинного слова. Типичная переменная целочисленного типа занимает в памяти машины 8, 16, 32 или 64 бит. Для многих криптографических алгоритмов требуются числа намного большего размера. Например, рекомендуемый размер открытого ключа для алгоритма RSA составляет 4 Кбит. Рассмотрим реализацию базовых арифметических операций над целыми числами большого размера. Для представления цифр больших чисел удобно использовать систему счисления с основанием b, равным 2m, где m – размер машинного слова. Это наиболее компактный способ представления больших чисел, позволяющий хранить все цифры в массиве слов-переменных. Алгоритм сложения Алгоритм сложения неотрицательных чисел достаточно прост: цифры числа складываются, начиная с младших разрядов к старшим. Если зафиксировано переполнение (т. е. при сложении получена цифра, большая максимально возможной в данной системе счисления), то происходит перенос значения в следующий разряд. Рассмотрим реализацию сложения неотрицательных n‑разрядных целых чисел (un‑1, …, u0)b и (vn‑1, …, v0)b по основанию b. Следующий алгоритм формирует их сумму (wn, wn‑1, …, w0)b, причем wn Î {0, 1}: ADD(u, v, n) j := 0; k := 0; while j < n do wj := uj + vj + k if wj ≥ b then wj := wj – b k := 1 else k := 0 j := j + 1 wn := k return (wn, …, w0) Заметим, что при работе этого алгоритма всегда выполняются соотношения uj + vj + k ≤ (b – 1) + (b – 1) + 1 < 2b, так что размер результата суммирования не превышает log22b = b + 1 разрядов. Приведенный алгоритм может использоваться и для сложения отрицательных чисел. Для этого следует использовать их представление в дополнительном коде. Алгоритм умножения Умножение больших чисел может быть выполнено традиционным школьным способом «в столбик». Однако вместо использования массива промежуточных результатов гораздо эффективнее добавлять к произведению каждую новую строку немедленно после ее вычисления. Если множимое состоит из m слов, множитель – из n слов, то произведение занимает не более m + n слов, независимо от того, выполняется знаковое или беззнаковое умножение. Рассмотрим реализацию умножения неотрицательных целых чисел (um‑1, …, u0)b и (vn‑1, …, v0)b по основанию b. Следующий алгоритм формирует их произведение (wm + n – 1, …, w0)b: MULTIPLY (w, v, m, n) forj = 0, …, m – 1 do wj := 0; j := 0; while j < n do if vj > 0 then i := 0; k := 0; while i < m do t := ui ∙ vj + wi+j + k: wi+j := t mod b; k := ; i := i + l; wj + m := k; else wj + m := 0; j := j + l; return (wm + n ‑ 1, …,w0) На каждом шаге алгоритма умножения выполняются неравенства 0 ≤ t < b2, 0 ≤ k < b. Умножение больших чисел выполняется проще для беззнаковых операндов. Знак произведения получается как результат операции «ИСКЛЮЧАЮЩЕЕ-ИЛИ» над разрядами знака множителей. Умножение целых чисел может быть существенно ускорено. Например, пусть u = bnU1 + U0, v = bnV1 + V0. Тогда (алгоритм Карацубы) uv = b2nU1V1 + bn(U1V0 + U0V1) + U0V0 = где С0 = U1V1, С1 = U0V0, С2 = (U0 + U1)(V0 + V1). Алгоритм Карацубы сводит задачу умножения двух чисел к нескольким задачам умножения чисел меньшей разрядности. Разбиение может осуществляться рекурсивно до тех пор, пока разрядность не уменьшится до поддерживаемой аппаратно (т.е. пока n не достигнет размера машинного слова). В этом случае число элементарных умножений для алгоритма Карацубы асимптотически сходится к . Пример: 13 ∙ 27 = 100 ∙ 1 ∙ 2 + 10 ∙ (3 ∙ 7 + 1 ∙ 2) + 3 ∙ 7 = 100 ∙ 2 + 10 ∙ (36 – Обобщением алгоритма Карацубы является алгоритм Тома–Кука, в котором множители могут разбиваться более чем на две части. Максимальной скоростью на сегодняшний день обладает алгоритм умножения на основе быстрого преобразования Фурье. В этом случае цифры произведения получаются как коэффициенты свертки цифр множителей, посчитанные с учетом переносов значений между коэффициентами. Деление Основная сложность при реализации классического метода деления «в столбик» состоит в необходимости угадывать разряды частного на каждой итерации алгоритма. Этот процесс должен быть формализован. Прежде всего заметим, что деление т-разрядного числа на п-разрядное (т > п) сводится к последовательности делений (п + 1)-разрядных чисел и на n-разрядное число v,причем 0 ≤ u/v < b, где b – основание системы счисления. Таким образом, необходимо построить алгоритм для нахождения q = , u = (un, un‑1, …, u0)b и Условие u/v < b может быть переформулировано как и/b < v,т. е. (12) В данном случае , при этом если q* превышает q,то превышение незначительно. Кроме того, если vn-1 ≥ , то . Это условие носит название условия нормализации. Его можно обеспечить, домножив делимое и делитель на . Дополнительно можно показать, что если , то q* < q,где r* = uпb + un–1 + q*vn–1. В противном случае Исходя из этих соображений, алгоритм вычисления частного m и остатка n от деления (um+n‑1, …, u0)b на (vn‑1, …, v0)b имеет вид
Некоторые фрагменты этого алгоритма выполняются очень редко, что затрудняет отладку. Задания 1. Реализуйте алгоритмы «в столбик» для вычисления суммы, произведения и частного двух целых чисел большой разрядности. 2. Реализуйте алгоритмы Карацубы для умножения целых чисел большой разрядности. 3. Сравните скорость работы и затраты памяти для реализованных в заданиях 1 и 2 алгоритмов умножения целых чисел большой разрядности. ©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.
|