При умножении двух целых беззнаковых числа размером в n бит результат, получаемый микропроцессором, будет длиной в 2n бит.
Простейший способ умножения целых беззнаковых чисел X×Y=Z есть суммирование множимого X с накоплением его столько раз, сколько единиц содержит значение множителя Y. Этот способ требует при больших значениях Y значительных затрат времени на выполнение многократных операций сложения, и поэтому применение его в компьютерах ограниченно.
Сокращение количества операций сложения при реализации умножения основано на методах совместного анализа цифр множителя. Эти методы дробят процесс получения произведения на ряд шагов, связанных с формированием частичных произведений (ЧП) – произведений множимого на отдельные разряды или группы разрядов множителя – и их суммированием, то есть формированием суммы частичных произведений (СЧП).
Методы умножения двоичных беззнаковых чисел основаны на представлении произведения в виде полинома:
, (2)
где – двоичные цифры множителя, – частичные произведения (ЧПi=X, если yi=1, и ЧПi=0, если yi=0).
Заметим, что умножение на степень 2i эквивалентно сдвигу множимого на i разрядов влево.
Формирование произведения, согласно формуле (2), представляется как последовательность таких действий:
-
обнуление СЧП;
-
анализ младшего разряда множителя: если y0=1, выполняется сложение ЧП0=X с СЧП и переход к п.3; если y0=0, сразу переход к п.3;
-
сдвиг множимого влево;
-
анализ очередного разряда множителя: если y1=1, выполняется сложение ЧП1∙21 с СЧП и переход к п.5; если y1=0, непосредственно переход к п.5;
-
сдвиг множимого влево;
-
анализ очередного y2 разряда множителя и т.д.
После анализа старшего yn-1 разряда множителя осуществляется последнее сложение с СЧП (если yn-1=1), и процесс прекращается. Результирующая СЧП является искомой. Очевидно, что неподвижную СЧП и сдвигаемое влево на n-1 разряд множимое необходимо размещать в 2n-разрядных форматах, причем операция сложения должна обрабатывать 2n-разрядные данные.
Рассмотрим на примере умножение двух целых беззнаковых чисел. Найдем произведение 45 и 29, пользуясь машинным алгоритмом. В десятичной системе счисления 45∙29=1305.
Переведем множимое и множитель в двоичную систему счисления: 4510=1011012, 2910=111012.
Шаг i
|
yi
|
ЧП
|
СЧП
|
0
|
1
|
101101
|
101101
|
1
|
0
|
1011010
|
101101
|
2
|
1
|
10110100
|
101101
+10110100
|
3
|
1
|
101101000
|
101101
+10110100
+101101000
|
4
|
1
|
1011010000
|
101101
+10110100
+101101000
+1011010000
10100011001
|
Таб.5
Итак, результат произведения 101000110012=130510. То есть, можно сделать вывод, что алгоритм работает правильно.
Очевидно, что при работе с однобайтовыми беззнаковыми числами результат таковым не будет. Так как он занимает 11 разрядов. Можно предположить, что в разрядной сетке результата будет 00011001, то есть в 2510. Проведем машинный эксперимент. Действительно, при отключенной проверке выхода результата за разрядную сетку, на экран выводится 25.
Упражнение 19. Напишите программу на Паскале, имитирующую процесс умножения двух целых беззнаковых чисел.
Решение.
var
temp,k: byte;
a,b,n,res:word;
begin
writeln('Введите два положительных числа a<255, b<255');
readln(a,b);{Ввод множимого и множителя}
res:=0; {Сумма частичных произведений}
k:=0; {Счетчик шагов, битов}
n:=1; {Переменная для вычисления значения очередного бита}
while k<=7 do {Пока не просмотрены все биты множителя b}
begin
temp:=n and b; {Находим значение очередного бита}
if temp<>0 {Если он не равен нулю, то вычисляем}
then res:=res+a; {очередное частичное произведение}
a:=a shl 1; {Сдвигаем множимое на один бит влево}
n:=n*2; {Будем рассматривать очередной бит}
k:=k+1;
end;
writeln('Произведение a*b=',res);
end.
Методы умножения беззнаковых чисел применимы и для вычисления произведения двоичных знаковых чисел в дополнительных кодах.
Проведем эксперимент. Попробуем умножить два знаковых целых числа по правилам умножения беззнаковых целых чисел.
В двоичном представлении
|
Беззнаковые числа
|
Знаковые числа
|
×11111111
|
×255
|
×-1
|
11111111
|
255
|
-1
|
1111111000000001
|
65025
|
-511
|
Можно сделать вывод, что правило умножения для беззнаковых целых чисел не подходит для знаковых чисел, представленных в дополнительном коде. Следовательно, просто переносить метод умножения беззнаковых чисел на знаковые нельзя.
Пусть целые двоичные сомножители X и Y представлены в дополнительном коде в n-разрядном формате, старший разряд которого используется для представления знака. При умножении этих чисел возможны четыре ситуации:
-
X>0, Y>0. Так как D(X, n)=X и D(Y, n)=Y, то D(X Y, n)=X Y, то есть результат умножения совпадает с произведением беззнаковых чисел.
-
X<0, Y>0. Согласно формуле (1), D(X<0, n)= 2n+X, и произведение, полученное методом умножения беззнаковых чисел, - псевдопроизведение – равно . Правильный же результат равен . Очевидно, что для получения правильного результата из псевдопроизведения необходимо к последнему прибавить 22n (эту операцию практически не надо выполнять, так как данное число выходит за рамки формата произведения) и вычесть множитель , то есть вычесть множитель, сдвинутый влево на n разрядов.
-
X>0, Y<0. Эта ситуация аналогична предыдущей. Для получения правильного произведения необходимо вычесть множимое, сдвинутое влево на n разрядов.
-
X<0, Y<0. Так как D(X<0, n)=2n+X и D(Y<0, n)=2n+Y, то псевдопроизведение равно , а правильное произведение . Следовательно, для получения правильного произведения из псевдопроизведения необходимо вычесть число , то есть вычесть и множитель и множимое, сдвинутые предварительно на n разрядов влево.
Упражнение 20. Приведите примеры для каждого рассмотренного случая.
Решение.
-
При умножении двух положительных знаковых чисел, алгоритм полностью совпадает с алгоритмом умножения беззнаковых чисел. См. примеры выше.
-
Пусть X= -5, а Y=32. Дополнительный код числа X равняется D(X, 8)=11111011, Y=00100000. Тогда псевдопроизведение равно:
×11111011
|
|
×-5
|
00100000
|
|
32
|
0001111101100000
|
|
? -160
|
Найдем реальное произведение, отняв от полученного псевдопроизведения следующую поправку:
-0001111101100000
|
|
|
0010000000000000
|
|
|
1..1111111101100000
|
|
|
Число 1111111101100000 является дополнительным кодом числа -160. Следовательно, результат правильный.
-
Данный случай решается аналогично предыдущему.
-
Пусть X= -5, а Y= -32. Тогда D(X, 8)=11111011, D(Y, 8)=11100000. Отсюда, псевдопроизведение равно:
×11111011
|
|
×-5
|
11100000
|
|
-32
|
1101101110100000
|
|
? 160
|
Найдем реальное произведение, отняв от полученного псевдопроизведения следующую поправку
-1101101110100000
|
|
|
11101101100000000
|
|
|
1..0000000010100000
|
|
|
Итак, в разрядной сетке осталось число +160. Что и требовалось получить.
Упражнение 21. Придумайте еще один способ перемножения знаковых чисел в дополнительных кодах. Ответ: перемножение модулей чисел, вычисление знака результата при помощи сравнения старших разрядов множителей. Если разряды равны, то ответ положительный (представляется в прямом коде). Если разряды не равны, то ответ отрицательный (представляется в дополнительном коде).
Упражнение 22. Оцените, какой из предложенных алгоритмов умножения знаковых чисел более рациональный (быстрый по количеству операций и хранимой информации).
Над множеством целых чисел со знаком операция деления не определена, поскольку в общем случае ее результатом будет вещественное число. Однако допустимыми являются операции целочисленного деления и нахождения остатка от целочисленного деления (те, что в паскале обозначаются div и mod). Точнее, значения обеих величин находятся одновременно в одной процедуре, которая в конечном счете сводится к последовательности вычитаний или, еще точнее, сложений с дополнительным кодом делителя.
Упражнение 23. Напишите программу на Паскале, имитирующую работу операций целочисленного деления и нахождения остатка от деления.
var
a,b,ost,chast: word;
begin
writeln('Введите делимое и делитель a и b');
readln(a,b);
ost:=a; {Остаток от деления}
chast:=0; {Целочисленное частное}
While ost>=b do {Пока остаток от деления больше делителя}
begin
chast:=chast+1; {Увеличиваем частное на единицу}
ost:=ost-b; {От остатка отнимаем делитель}
end;
writeln('Результат целочисленного деления равен',chast);
writeln('Остаток при целочисленном делении равен',ost);
end.
Достарыңызбен бөлісу: |