Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 [ 56 ] 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87

будете иметь дело со знаковыми числами, то получите 3 = -5. Однако и 11 и -5 имеют одно и то же представление в дополнительном коде (поскольку их разность равна 16), так что в обоих случаях в качестве мультипликативного обратного элемента используется одно и то же содержимое машинного слова.

Рассмотренная теорема непосредственно применима к задаче деления (знакового и беззнакового) на нечетное число d на W-битовом компьютере. Поскольку любое нечетное число является взаимно простьпй с 2", теорема гласит, что если d нечетно, то существует целое d (единственное в диапазоне от О до 2"" -1 или от -2"" до 2"" -1), такое, что dd а l(mod f). Следовательно, для любого п, являющегося делителем d, справедливо соотношение

= (rfs«J(mod2").

Другими словами, nfd можно вычислить путем умножения и на rf, после чего взять правые W6m полученного произведения.

Если делитель d представляет собой четное число, то пусть rf = rf • 2, где rfo нечетно, а it > 1. Тогда просто выполняется сдвиг числа п вправо на к позиций (устраняя нулевые биты), после чего выполняется умножение на rf (сдвиг можно выполнить и после операции умножения).

Ниже приведен код для деления на 7 числа п, кратного 7. Этот код дает корректный результат как при знаковом, так и при беззнаковом делении.

li M,0xB6DB6DB7 Мультипликативное обратное, (5*2**32+1)/7 mul q,M,n q = n/7

Вычисление мультипликативного обратного по алгоритму Евклида

Каким же образом можно вычислить мультипликативное обратное число? Стандартный метод- использование "расширенного алгоритма Евклида". Этот метод вкратце рассматривается далее в приложении к нашей основной задаче, а заинтересовавшимся читателям можно посоветовать обратиться к [49] и [39, раздел 4.5.2].

Пусть задан нечетный делитель d и нам требуется найти число х, такое, что

rf»; = l(modm),

причем в нашей задаче т = 2"" (где W- размер машинного слова). Это может быть выполнено, если будет решено в целых числах дг и у (положительных, отрицательных, равных 0) уравнение

dx + my = l.

Начнем с того, что сделаем d положительным, добавляя к нему достаточное количество раз число m (rf и d + km имеют одно и то же мультипликативное обратное). Затем запишем следующие уравнения (где rf,m > О):

rf(-l) + m(l)=»i-rf, (31,а)

rf(l) + m(0) = rf. (31,6)



Если d = l, поставленная задача решена, так как (31,6) показывает, что jc = l. В противном случае вычислим

Далее умножим уравнение (31,6) на g и вычтем его из (31,а). Это даст нам уравнение d{-\- q) + т{\) = т- d - qd = iem(m -d,d).

Это уравнение справедливо, поскольку мы просто умножили одно из уравнений на константу и вычли его из другого. Если Tem{m-d,d)=l, то задача решена (последнее уравнение и является решением) и x = -l-q .

Повторим описанный процесс с последними двумя уравнениями, получая новое уравнение. Будем продолжать эти действия до тех пор, пока в правой части уравнения не будет получена 1. Тогда множитель при d, приведенный по модулю /и, и будет представлять собой искомое мультипликативное обратное к d.

Если m-d<d , так что первое частное равно О, то третья строка будет точной копией первой, так что второе частное будет ненулевым. Кроме того, в разных источниках зачастую в качестве первой строки используется следующая:

d(0) + m{l) = m,

но в нашем приложении m = 2" невозможно представить в компьютере.

Лучше всего проиллюстрировать описываемый процесс на конкретном примере. Пусть /и=256 и d=7. Тогда процесс вычислений выглядит как показано ниже (для получения третьей строки используется q = [249/7] = 35).

7(-1)

256 (

= 249

7( 1)

256 (

7(-36)

256 (

7( 37)

256 (-

1)

7(-73)

256 (

Таким образом, мультипликативным обратным по модулю 256 числа 7 является -73 (или, используя числа из диапазона от О до 255, число 183). Проверяем: 7 • 183 = 1281 s l(mod 256).

Начиная с третьей строки, числа в правом столбце представляют собой остатки от деления чисел, расположенных выше, так что это строго убывающая последовательность неотрицательных чисел, которая, таким образом, должна завершиться О (в примере выше для этого требуется еще один шаг). Кроме того, число перед О должно быть 1 по следующей причине. Предположим, что последовательность остатков завершается некоторым числом Ь, не равным 1, после которого идет число 0. Тогда целое, предшествующее Ь, должно быть кратным b (скажем, числом кЬ) с тем, чтобы следующим остатком в последовательности было число 0. Такие же рассуждения приводят к выводу, что для того, чтобы получить остаток Ь, предшествующим jt,f»

числом должно быть kkjb + b. Продолжая эту последовательность, вы увидите, что

каждое из этих чисел должно быть кратно Ь, включая числа из первых двух строк, которые равны m-d и и являются взаимно простыми.



Приведенное выше рассуждение является неформальным доказательством того, что рассматриваемый процесс завершается, причем наличием 1 в правом столбце, а следовательно, находит мультипликативное обратное d число.

Для проведения данных вычислений на компьютере заметим, что если rf < О, то к нему необходимо прибавить г". Однако в случае арифметики, использующей дополнительный к 2 код, это делать не обязательно; достаточно просто рассматривать d как беззнаковое число, независимо от того, как именно его рассматривает приложение.

Вычисление q должно использовать беззнаковое деление.

Заметим, что все вычисления можно выполнять по модулю т, так как это никак не влияет на правый столбец (его значения все равно остаются в диапазоне от О до m -1). Это важно, так как позволяет нам выполнять вычисления с "одинарной точностью", используя беззнаковую компьютерную арифметику по модулю 2.

Большинство величин в рассматриваемой таблице не обязательно должны бьпъ представлены при вычислениях, например столбец множителей при 256, поскольку при решении уравнения dx + my = \ нас не интересует значение у. Нет необходимости и в представлении d в первом столбце. Оставляя в таблице только необходимое, получим ее сокращенный вид.

255 249 1 7

220 4

37 3

183 1

Программа на языке С для проведения этих вычислений представлена в листинге 10.4.

Листинг 10.4. Алгоритм Евклида поиска мультипликативного обратного по модулю 2

unsigned mulinv(unsigned d) d должно быть нечетно {

unsigned xl, vl, x2, v2, x3, v3, q;

xl = OxFFFFFFPF; vl = -d;

x2 = 1; v2 = d;

while (v2 > 1)

q = Vl/v2;

x3 = xl - q*x2; v3 = vl - q*v2; xl = x2; vl = v2; x2 = x3; v2 = v3;

return(x2);

Причина использования условия цикла v2 > i вместо более естественного v2 ! = i заключается в том, что если при использовании последнего условия функции будет ошибочно передано четное значение, то цикл может никогда не завершиться (если аргумент d четен, v2 никогда не получит значение 1, но в конечном итоге примет значение 0).

Что же вычисляет данная программа, если передать ей четный аргумент? Как и следует из формул, она вычисляет число jc, такое, что dx = O(mod 2"), которое вряд ли может

оказаться полезным. Однако минимальные изменения в программе (изменение условия цикла на v2 ! = О и возврат значения х1 вместо х2) приводят к вычислению ею числа jc,



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 [ 56 ] 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87