IPB
ЛогинПароль:

> Прочтите прежде чем задавать вопрос!

1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code], либо быть опубликованы на нашем PasteBin в режиме вечного хранения.
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!

2 страниц V  1 2 >  
 Ответить  Открыть новую тему 
> Умножение длинных целых чисел в дополнительном коде, Ошибка
сообщение
Сообщение #1


Новичок
*

Группа: Пользователи
Сообщений: 18
Пол: Женский

Репутация: -  0  +


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

var
temp,i,j: longint;
n,n2,res:longint;
s,s2,sim,sim2:string;
alf:set of char;
ch:char;
p,p2,s1,s22,por,pr,apr,step,k:longint;
a,b:longint;
apr2:longint;
arr: array[1..10] of string;
c,c2:boolean;
begin
c:=false; c2:=false;
alf:=['0'..'9'];
Write('vvedite pervoe chislo: ');
Readln(s);
Write('vvedite vtoroe chislo: ');
Readln(s2);
n:=length(s);
n2:=length(s2);
sim:='';p:=0; sim2:=''; p2:=0;
For i:=1 to n do begin {vudelenie cifr iz 1 stroki}
If s[i] in alf then sim:=sim+s[i];
If s[i]='-' then c:=true;
end;
For j:=1 to n2 do begin {vudelenie cifr iz 2 stroki}
If s2[j] in alf then
sim2:=sim2+s2[j];
If s2[j]='-' then c2:=true;
end;
For i:=1 to length(sim) do begin {perevod iz stroki v chislo (1)}
s1:=ord(sim[i])-ord('0');
p:=p*10+s1;
end;
For j:=1 to length(sim2) do begin {perevod iz stroki v chislo (2)}
s22:=ord(sim2[j])-ord('0');
p2:=p2*10+s22;
end;
Writeln('chisla: ',p,' ',p2);
a:=0; step:=1;n:=1;
While p>=2 do begin {perevod iz 10i ss v 2ss (1)}
pr:=p div 2;
apr:=p-pr*2;
a:=a+apr*step;
p:=pr;
step:=step*10;
n:=n+1;
If p=1 then a:=step+a;
end;
Writeln('dvoichnoe predstavlenie 1 chsla: ',a);
step:=1; b:=0; por:=1; {perevod iz 10i ss v 2ss (2)}
While p2>=2 do begin
pr:=p2 div 2;
apr:=p2-pr*2;
b:=b+apr*step;
p2:=pr;
step:=step*10;
If p2=1 then b:=step+b;
por:=por+1;
end;
Writeln('dvoichnoe predstavlenie 2 chisla: ',b);
Writeln('kolichestvo cifr 1: ',n);
Writeln(' 2: ',por);
If c=true then begin
apr:=a; pr:=a; a:=0; k:=1; {perevod 1go chisla v dopolnitelnui kod}
For i:=1 to n do begin
apr:=pr mod 10;
pr:=pr div 10;
If apr=0 then apr2:=1;
If apr=1 then apr2:=0;
a:=a+apr2*k;
k:=k*10;
end;
k:=a mod 10;
If k=1 then begin
apr:=0;
a:=(a div 10)*10+apr;
end;
If k=0 then begin
k:=1;
a:=(a div 10)*10+apr;
end;

end;
{ If c=false then a:=p;}
Writeln('v dopolnit kode 1: ',a);
If c2=true then begin
apr:=b; pr:=b; b:=0; k:=1; {perevod 2go chisla v dopolnitelnui kod}
For j:=1 to por do begin
apr:=pr mod 10;
pr:=pr div 10;
If apr=0 then apr2:=1;
If apr=1 then apr2:=0;
b:=b+apr2*k;
k:=k*10;
end;
k:=b mod 10;
If k=1 then begin
apr:=0;
b:=(b div 10)*10+apr;
end;
If k=0 then begin
k:=1;
b:=(b div 10)*10+apr;
end;
end;
{ If c2=false then b:=p2;}
Writeln('v dopolnit kode 2: ',b);
res:=0; {ymnozenie}
k:=0;
n:=1;
While k<=64 do begin
temp:=n and b;
if temp<>0
then res:=res+a;
a:=a shl 1;
n:=n*2;
k:=k+1;
end;
writeln('rezyltat v dopolnitelnom kode: ',res);
readln;
end.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Знаток
****

Группа: Пользователи
Сообщений: 481
Пол: Мужской
Реальное имя: Федосеев Павел

Репутация: -  9  +


происходит переполнение разрядной сетки переменной n.
Если ограничить множители 8-ю битами, т.е. диапазоном (-128...+127), то
 While k<=64 do begin     <---- k<8
temp:=n and b;
if temp<>0
then res:=res+a;
a:=a shl 1;
n:=n*2; <--- n:=n shl 1;
k:=k+1;
end;


В дополнительный код неправильно переводит отрицательные числа.
Опять же, если ограничиться 8-ю битами, то число (-210)=-102=1111 11102.
Алгоритм такой: все 8 бит исходного числа инвертируешь и прибавляешь 1.
(-210)=-102=1111 11012 доп+1=1111 11102 доп
При умножении двух чисел нужно умножать их модули, а потом с учётом знака результата переводить или не переводить в дополнительный код.

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

А ещё, приведи исходную постановку задачи.

Сообщение отредактировано: Федосеев Павел -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Новичок
*

Группа: Пользователи
Сообщений: 18
Пол: Женский

Репутация: -  0  +


Цитата(Федосеев Павел @ 24.03.2012 17:54) *

происходит переполнение разрядной сетки переменной n.
Если ограничить множители 8-ю битами, т.е. диапазоном (-128...+127), то
 While k<=64 do begin     <---- k<8
temp:=n and b;
if temp<>0
then res:=res+a;
a:=a shl 1;
n:=n*2; <--- n:=n shl 1;
k:=k+1;
end;


В дополнительный код неправильно переводит отрицательные числа.
Опять же, если ограничиться 8-ю битами, то число (-210)=-102=1111 11102.
Алгоритм такой: все 8 бит исходного числа инвертируешь и прибавляешь 1.
(-210)=-102=1111 11012 доп+1=1111 11102 доп
При умножении двух чисел нужно умножать их модули, а потом с учётом знака результата переводить или не переводить в дополнительный код.

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


спасибо большое. поняла. правда 8 бит это немало? мне нужно переводить именно длинные числа... попробовала для длинных не совсем то что нужно выдает...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Профи
****

Группа: Пользователи
Сообщений: 652
Пол: Мужской
Реальное имя: Алексей

Репутация: -  20  +


Привидите пример и резальтат.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Знаток
****

Группа: Пользователи
Сообщений: 481
Пол: Мужской
Реальное имя: Федосеев Павел

Репутация: -  9  +


Можно взять и больше, но дополнительный код для отрицательных чисел будет длиннее. Так для 16 разрядов -210=1111 1111 1111 11102 доп.
для длинных чисел применяют другой тип хранения чисел - массив или строку. И соответственно определяют в виде процедур все операции над числами (+, -, *, /). Имея простые операции уже и реализуют все остальные вычисления. На форуме должны быть примеры.

Приведи исходный текст задания.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Новичок
*

Группа: Пользователи
Сообщений: 18
Пол: Женский

Репутация: -  0  +


Цитата(Krjuger @ 24.03.2012 18:13) *

Привидите пример и резальтат.


любые числа. диапозон дб Longint -2147483648..2147483647 .
25 и 26 вводимые. результат в двоичн. дополнит. 10010001010


Добавлено через 5 мин.
пользователь должен ввести любое десятичное число. программа перевести его в дополнительный код и перемножить. независимо отрицателньое оно или положительное. результат выдается в десятичном же числе. Умножаются длинные целые числа

Сообщение отредактировано: olven -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Знаток
****

Группа: Пользователи
Сообщений: 481
Пол: Мужской
Реальное имя: Федосеев Павел

Репутация: -  9  +


Я не могу понять смысл задания.

Вот описание работы с длинными положительными целыми числами.

Добавим к тем реализациям дополнительное поле "знак" и сможем работать и с отрицательными.

Но как к ним прикрутить дополнительный код?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Новичок
*

Группа: Пользователи
Сообщений: 18
Пол: Женский

Репутация: -  0  +


Цитата(Федосеев Павел @ 24.03.2012 19:30) *

Я не могу понять смысл задания.

Вот описание работы с длинными положительными целыми числами.

Добавим к тем реализациям дополнительное поле "знак" и сможем работать и с отрицательными.

Но как к ним прикрутить дополнительный код?


смотрела эту тему.. всё что поняла из кода это то что они там кажется столбиком перемножают... мне необходдимо по алгоритму. сложил - сдвинул, сложил-сдвинул.. как я и пыталась
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Знаток
****

Группа: Пользователи
Сообщений: 481
Пол: Мужской
Реальное имя: Федосеев Павел

Репутация: -  9  +


Я не могу понять смысл задания.

Как прикрутить дополнительный код?
------------------------------------------------------------------------
Может быть речь идёт о типе LongInt?
Т.е. всё - и мнгожители и произведение умещается в тип LongInt?
Тогда решение задания получается таким:
1. Ввод 1-го числа в виде строки s1.
Далее просто преобразование строки в число LongInt (забываем про встроенные возможности языка).
2. Преобразование s1 в беззнаковое (пока) число c1 (типа LongInt) и знак sign1 (boolean)
3. Если c1 должно быть отрицательным, то c1:=(NOT c1)+1. Вернее здесь будет чуть иначе, но это детали.
Тоже самое и со вторым числом.
Потом умножаем c1 на c2 и выводим результат средствами языка (writeln).

Кажется, что я подменяю условие...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Новичок
*

Группа: Пользователи
Сообщений: 18
Пол: Женский

Репутация: -  0  +


Цитата(Федосеев Павел @ 24.03.2012 20:33) *

Я не могу понять смысл задания.

Как прикрутить дополнительный код?
------------------------------------------------------------------------
Может быть речь идёт о типе LongInt?
Т.е. всё - и мнгожители и произведение умещается в тип LongInt?
Тогда решение задания получается таким:
1. Ввод 1-го числа в виде строки s1.
Далее просто преобразование строки в число LongInt (забываем про встроенные возможности языка).
2. Преобразование s1 в беззнаковое (пока) число c1 (типа LongInt) и знак sign1 (boolean)
3. Если c1 должно быть отрицательным, то c1:=(NOT c1)+1. Вернее здесь будет чуть иначе, но это детали.
Тоже самое и со вторым числом.
Потом умножаем c1 на c2 и выводим результат средствами языка (writeln).

Кажется, что я подменяю условие...


там нет ограничений каким способом. главное чтобы выполнялись условия, то что ты написал это просто мой метод я пыталась решить это так, но для длинных чисел он не работает, из твоих слов поняла, что нужно писать по другому, представлять формат в виде строк или массива. но как это делают я без понятия. пытаюсь разобраться
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Знаток
****

Группа: Пользователи
Сообщений: 481
Пол: Мужской
Реальное имя: Федосеев Павел

Репутация: -  9  +


Ага, значит в оригинальном условии задачи фраза "дополнительный код" не упоминалась?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Новичок
*

Группа: Пользователи
Сообщений: 18
Пол: Женский

Репутация: -  0  +


Цитата(Федосеев Павел @ 24.03.2012 21:22) *

Ага, значит в оригинальном условии задачи фраза "дополнительный код" не упоминалась?

упоминалась,иначе я б не стала столько мучиться....
я думаю может нужно просто если положит числа то в двоичном прямом коде перемножить. а если отриц то перевести в дополнительный и там попробовать?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Новичок
*

Группа: Пользователи
Сообщений: 18
Пол: Женский

Репутация: -  0  +


Длинная арифметика
попробовала умножение описанноездесь. оно тоэе не работает для длинных... ии я что то не понимаю? почему при числах больше 10 переводя в двоичный код результат выдается неверный?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Знаток
****

Группа: Пользователи
Сообщений: 481
Пол: Мужской
Реальное имя: Федосеев Павел

Репутация: -  9  +


Приведи пример, на котором возникла ошибка (и данные и программу). Сейчас я попробовал умножение из модуля dlinna - показал верный результат. Никаких дополнительных преобразований в двоичный код там не предполагается. В модуле есть штатные средства визуализации - WriteLong.
Ты уже столько сил затратила на изучение различныных форматов данных... Может стоит уточнить у преподавателя, что требуется от учебной программы?

Цитата
любые числа. диапозон дб Longint -2147483648..2147483647 .
25 и 26 вводимые. результат в двоичн. дополнит. 10010001010

Добавлено через 5 мин.
пользователь должен ввести любое десятичное число. программа перевести его в дополнительный код и перемножить. независимо отрицателньое оно или положительное. результат выдается в десятичном же числе. Умножаются длинные целые числа

Если взять это за основу, то получается, что требуется "забыть" о существовании штатных Write и Read, и самостоятельно пересоздать их. Затем "забыть" о существовании типа longint и создать свои процедуры для работы с ним. Вот без реализации умножения и деления (по-сути с чего начался топик):
TYPE
TLongBin = LongInt;

VAR
LongBin_Error : Integer;

PROCEDURE LongBin_Add ( m1,
m2 : TLongBin;
VAR Res : TLongBin);
BEGIN
END;

PROCEDURE LongBin_Sub ( m1,
m2 : TLongBin;
VAR Res : TLongBin);
BEGIN
END;

PROCEDURE LongBin_Mul ( m1,
m2 : TLongBin;
VAR Res : TLongBin);
BEGIN
Res:=m1*m2;
END;

PROCEDURE LongBin_Div (m1,
m2 : TLongBin;
VAR Res : TLongBin);
BEGIN
END;

PROCEDURE LongBin_Read (VAR Num : TLongBin);
VAR
s : String;
i,
start : Integer;
Sign : BOOLEAN;
BEGIN
ReadLn(s);
Sign:=(s[1]='-');
if Sign then
start:=2
else
start:=1;
for i:=start to Length(s) do begin
if NOT (s[i] in ['0'..'9']) then begin
LongBin_Error:=1;
Exit;
end;
Num:=Num*10;
Num:=Num+(Ord(s[i])-Ord('0'))
end;
{если число отрицательное, то преобразуем в дополнительный код}
if Sign then begin
Num:=NOT(Num)+1;
end;
END;

PROCEDURE LongBin_WriteD( Num : TLongBin);
BEGIN
Write(Num);
END;

PROCEDURE LongBin_WriteB( Num : TLongBin);
VAR
i : Integer;
s : String;
Mask : TLongBin;
BEGIN
Mask:=1;
for i:=1 to (SizeOf(TLongBin)*8-1) do
Mask:=Mask shl 1;
s:='';
for i:=1 to SizeOf(TLongBin)*8 do begin
if (Mask AND Num)<>0 then
s:=s+'1'
else
s:=s+'0';
Mask:=Mask shr 1;
end;
Write(s);
END;

VAR
c1,
c2,
c3 : TLongBin;
BEGIN
LongBin_Read(c1);
LongBin_Read(c2);
LongBin_Mul(c1, c2, c3);
WriteLn('===============');
LongBin_WriteD(c1);
Write(' ');
LongBin_WriteB(c1);
WriteLn;
LongBin_WriteD(c2);
Write(' ');
LongBin_WriteB(c2);
WriteLn;
LongBin_WriteD(c3);
Write(' ');
LongBin_WriteB(c3);
WriteLn;
END.

-----------------------------
Добавлю во вложении исправленный вариант. В нём реализовано сложение, вычитание и умножение. Если реализовать деление, то можно корректно оформить и вывод в десятичном виде. Тогда размер длинных чисел можно будет не ограничивать 4 байтами.Прикрепленный файл  LongBin.pas ( 5.09 килобайт ) Кол-во скачиваний: 754


Сообщение отредактировано: Федосеев Павел -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #15


Новичок
*

Группа: Пользователи
Сообщений: 18
Пол: Женский

Репутация: -  0  +


спасибо большое, попробую разобраться.... по моему я уже сама запуталась...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #16


Новичок
*

Группа: Пользователи
Сообщений: 18
Пол: Женский

Репутация: -  0  +


скажите пожалуйста можно ли добавить в программу часть которая показывает это умножение?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #17


Знаток
****

Группа: Пользователи
Сообщений: 481
Пол: Мужской
Реальное имя: Федосеев Павел

Репутация: -  9  +


А что нужно показать? В процедуре LongBin_Mul простое умножение в столбик (правда, желательно ввести проверку на переполнение разрядной сетки - но ведь это всего лишь пример). Далее в программе приводится пример использования этой процедуры "LongBin_Mul(c1, c2, c3);", где c1, c2 - первый и второй множители, а c3 - их произведение.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #18


Новичок
*

Группа: Пользователи
Сообщений: 18
Пол: Женский

Репутация: -  0  +


Цитата(Федосеев Павел @ 24.04.2012 9:38) *

А что нужно показать? В процедуре LongBin_Mul простое умножение в столбик (правда, желательно ввести проверку на переполнение разрядной сетки - но ведь это всего лишь пример). Далее в программе приводится пример использования этой процедуры "LongBin_Mul(c1, c2, c3);", где c1, c2 - первый и второй множители, а c3 - их произведение.


как они перемножаются пошагово,показать как осуществляется умножение в дополнительном коде,допустим человеку который не умеет этого делать, как то так сказали. можно еще вопрос о функции hi() и lo() как они выделяют байты?

Сообщение отредактировано: olven -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #19


Знаток
****

Группа: Пользователи
Сообщений: 481
Пол: Мужской
Реальное имя: Федосеев Павел

Репутация: -  9  +


1) hi/lo
- hi - возвращает старший байт слова (для типа word) или старшее слово (для типа longint). В контексте данной процедуры - старший байт слова (word).
- lo - аналогично hi, только возвращает младшую часть. В нашем случае младший байт слова.
2) В процедуре умножения в дополнительном коде как такового нет. В самом начале процедуры выясняются знаки множителей (Sign1 и Sign2) и вычисляется знак результата (SignRes). Далее берётся модуль каждого множителя (LongBin_Abs) и перемножаются именно модули (положительные числа). После перемножения, если нужно (SignRes == TRUE) результат делается отрицательным - переводится в дополнительный код.
В принципе, при умножении в столбик мы тоже так и поступаем - умножаем модули чисел и определяем знак результата.
3) Если будет достаточно показать входные числа, затем их абсолютные значения, абсолютное, а затем и знаковое значение произведения, то см. в аттаче. Если требуется показать всё умножение столбиком, то там слишком много переделывать.

Сообщение отредактировано: Федосеев Павел -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #20


Новичок
*

Группа: Пользователи
Сообщений: 18
Пол: Женский

Репутация: -  0  +


Цитата(Федосеев Павел @ 24.04.2012 14:59) *

1) hi/lo
- hi - возвращает старший байт слова (для типа word) или старшее слово (для типа longint). В контексте данной процедуры - старший байт слова (word).
- lo - аналогично hi, только возвращает младшую часть. В нашем случае младший байт слова.
2) В процедуре умножения в дополнительном коде как такового нет. В самом начале процедуры выясняются знаки множителей (Sign1 и Sign2) и вычисляется знак результата (SignRes). Далее берётся модуль каждого множителя (LongBin_Abs) и перемножаются именно модули (положительные числа). После перемножения, если нужно (SignRes == TRUE) результат делается отрицательным - переводится в дополнительный код.
В принципе, при умножении в столбик мы тоже так и поступаем - умножаем модули чисел и определяем знак результата.
3) Если будет достаточно показать входные числа, затем их абсолютные значения, абсолютное, а затем и знаковое значение произведения, то см. в аттаче. Если требуется показать всё умножение столбиком, то там слишком много переделывать.


плохо.. ладно, понятно.. спасибо
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

2 страниц V  1 2 >
 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 12.09.2025 8:57
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name