Версия для печати темы
Пикап Форум - Всемирный форум пикаперов _ Курилка _ Паскаль
Автор: DriftKing 11.12.2007, 21:45
Люди, я туплю страшно. Помогите :?
Вообщем задача: Умножить два длинных числа (длинная арифметика).
Дано: Два файла: 1й: 1я строка- длинна 1го числа;2я строка- длинная 2го числа; 3я строка- 1е число; 4я строка- 2е число.
2й: в нем результат умножения.
Числа заносятся в массивы. перемножаются, и со сдвигом записываются в двумерный массив. Числа с двумерного массива сумируются, и результат заносится в обычный массив. (Вообщем как в столбик, через массивы).
Воть, если что несовсем понятно - спрашивайте. А процедурка нужна поскорее. Ибо последнюю лабу могу завалить :?: :idea:
ЗЫ в инэте смотрел, то что нужно не нашел.
Автор: Седрик 11.12.2007, 23:57
(DriftKing)
Люди, я туплю страшно. Помогите :?
Вообщем задача: Умножить два длинных числа (длинная арифметика).
Дано: Два файла: 1й: 1я строка- длинна 1го числа;2я строка- длинная 2го числа; 3я строка- 1е число; 4я строка- 2е число.
2й: в нем результат умножения.
Числа заносятся в массивы. перемножаются, и со сдвигом записываются в двумерный массив. Числа с двумерного массива сумируются, и результат заносится в обычный массив. (Вообщем как в столбик, через массивы).
Воть, если что несовсем понятно - спрашивайте. А процедурка нужна поскорее. Ибо последнюю лабу могу завалить :?: :idea:
ЗЫ в инэте смотрел, то что нужно не нашел.
Иди Кнута читай ... прохрамисст ))
Автор: DriftKing 12.12.2007, 0:17
Я бы с радостью, так у меня времени до пятницы
Упрощу задачу, я кое-что уже сделал. Нужно это:
- Есть двумерный массив. Нужно найти сумму его елементов, так, как бы мы сумировали их в столбик.
Допустим вот:
00123
05430
70800
00040
-------
76393
:?
Автор: DriftKing 12.12.2007, 0:18
Код написал, проимитировал на бумаге, работает. А в программе считает неверно
Автор: Eternalko 12.12.2007, 3:20
Не знаю на каком это языке
Экспромт
//0.КОД И КАММЕНТЫ ЧИТАТЬ ПО ЦИФРАМ!!!! По номерам.
a=new Array; //1. Создаем наш 2Д массив. По трад. будет. а
getIntToArray(a);//2. Заносим туда нашу матрицу. Твоя табличка сложения
funnction sum(array a) //3. Функция, которая как-бы производит сумму этого столбика:)
{
res=new Array; //4.Это наш результат. Будущий) ВАЖНО! Пишу задом наперед!!!! См. каммент №16
int tmp; //5.Для помощи. Тут храниться сумма одного столбика
int k=0,l=0; //6. Доп. переменные. К. счетчик.
for(i=a.getLenght;i>0;i--) //7. "Ставим" "себя" в прав. угол. a.getLenght это ДЛИННА массива. Просто число!
{
while(tmp) //11.Пока тмп больше "0". Будем записывать число за числом из результата нашего столбца в массив. Десяток за десятком
{
l=k; //12. Тут l будет нашим счетчиком чтоб не k "портить".
res[l]=+tmp % 10; //13. Записывам(добавляем) еще один десяток
l++; //14. увеличиваем, чтоб след. десяток. добавить....
tmp=tmp/10; //15. уменьшаем tmp на 10. На посл. цифру котор. занесли в результат.
}
k++; //16. увелич. счетчик эл-та рез-та.
for(j=a.getHeight;j>0;j--) //8. Теперь в нижн. прав. угол.
{
tmp+=a[j][i]; //9. Снизу(!) вверх суммируем ВСЕ числа. Сумма столбика:)
}
}
return reverse(res);//17. Возвращаем наш результат. Вот он супер массив число. Только надо обернуть его, чтоб правильно записалось:)
}
sum(a);^_0
Автор: Bordosten 12.12.2007, 10:33
Дрифт отключай пенис и включай мозг
Автор: FalseNegative 12.12.2007, 12:21
А в чём трабл-то? Суммирование само по себе просто как мычание... (хотя, давно не писал на паскакале этом, может напутал чегой...)
program arraysum;
var tosum: array [1...100,1..100] of Integer; //Как вариант, - array [] of 0..9;
actualwidth,actualheight: Integer;
aresult: array [1..100] of Integer;
begin
//читаем исходный массив.
for i := 1 to actualwidth do
begin
aresult := 0; //ВАЖНО! В Паскале нет автоинициализации!
for j := 1 to actualheight do
begin
aresult[i]:=aresult[i]+tosum[i,j];
end;
end;
//выводим результатъ
end.
Автор: FalseNegative 12.12.2007, 12:38
или вам ещё перенос нужен? т.е.
19
19
--
38
а не
19
19
--
2(18)?
тады так:
program arraysum;
var tosum: array [1...100,1..100] of Integer; //Как вариант, - array [] of 0..9;
actualwidth,actualheight,resultwidth,cnt,carry: Integer;
aresult: array [1..100] of Integer;
go_on:boolean;
begin
//читаем исходный массив.
for i := 1 to actualwidth do
begin
aresult := 0; //ВАЖНО! В Паскале нет автоинициализации!
for j := 1 to actualheight do
begin
aresult[i]:=aresult[i]+tosum[i,j];
end;
end;
go_on:=true;// или наоборот?
cnt:=1;
carry:=0;
while go_on do
begin
aresult[cnt]:=aresult[cnt]+carry;
carry:=aresult[cnt] div 10;
aresult[cnt]:=aresult[cnt] mod 10;
cnt:=cnt+1;
go_on:=NOT (carry=0 AND aresult[cnt]=0);//Тьху, надо NOT исправил.
end;
resultwidth:=cnt-1;//
//выводим результатъ
end.
Автор: DriftKing 12.12.2007, 19:24
Всем большое пасибо
Особенно тебе, Негетив. Мне с переносом нужно было))
Етерналко, спс тоже) Это код на С++. Я его знаю, но учить в универе бум тока в след году.
Автор: DriftKing 12.12.2007, 19:57
(FalseNegative)
или вам ещё перенос нужен? т.е.
19
19
--
38
а не
19
19
--
2(18)?
тады так:
program arraysum;
var tosum: array [1...100,1..100] of Integer; //Как вариант, - array [] of 0..9;
actualwidth,actualheight,resultwidth,cnt,carry: Integer;
aresult: array [1..100] of Integer;
go_on:boolean;
begin
//читаем исходный массив.
for i := actualwidth downto 1 do
begin
aresult[i] := 0; //ВАЖНО! В Паскале нет автоинициализации!
for j := 1 to actualheight do
begin
aresult[i]:=aresult[i]+tosum[i,j];
end;
end;
go_on:=true;// или наоборот?
cnt:=actualwidth; //actualwidth и actualheight одинаковые, поэтому безразници
carry:=0;
while go_on do
begin
aresult[cnt]:=aresult[cnt]+carry;
carry:=aresult[cnt] div 10;
aresult[cnt]:=aresult[cnt] mod 10;
cnt:=cnt-1;
go_on:=NOT ((carry=0) AND (aresult[cnt]=0));//Тьху, надо NOT исправил.
end;
resultwidth:=cnt-1;// это не нужно
//выводим результатъ
end.
Все отлично, только немного подправить нужно было. Красным дописал что нужно и убрал что нет)
[/color][color=#444444]
Автор: FalseNegative 12.12.2007, 21:51
Esli u tebja mladshie razrjady v starshih elementah, to s etim kodom vozmozhen access violation na popytke chtenija result[0].
neponjatno kuda devatj dp. razrjady.
i da, tam slozhenie vmesto umnozhenija.
Sorry, pishu s telefona.
Автор: Eternalko 12.12.2007, 23:54
А может так оптимальней будет....
program arraysum;
var tosum: array [1...,1...] of Integer; //Почему он должен быть определен?? Вдруг числа оч. большие:)))
actualwidth,actualheight,colsum,k,l: Integer;
aresult: array [1..100] of Integer;
begin
for i := actualwidth downto 1 do
begin
while colsum do
begin
l:=k;
aresult[l]:=aresult[l]+colsum mod 10;
colsum:=colsum div 10
l:=l+1;
end;
k:=k+1;
for j:= actualheight downto 1 do
begin
colsum:=colsum+tosum[j,i];
end;
end;
end;
[/code]
Автор: Eternalko 12.12.2007, 23:56
А... И еще все переменные должны быть по нулям
В начале программы)
Автор: DriftKing 13.12.2007, 1:11
Етерналко, может и оптимальнее, в паскаль не вставлял, ибо ты юзаешь сдесь динамический массив, а они появляются только в делфи, т.е. в паскале тебе выдаст ошибку
Нужно указывать от 1 .. и до какого-то определенного числа. (кстати я пробывал считать в программе число в переменную, потом вызвать процедуру, и сделать массив 1..та переменная. Всеравно не вышло, хотя переменную я считал раньше нежели определил массив, и значение так же передал в процедуру, т.е. в делфи/Си все было бы Окей.
Негетив, Я написал процедуру умножения. Только трабл такой получается. Считает оно все правильно, но только если массивы до 10. Т.е. мое "длинное" число максимум из 10 цыфр. Если больше 10 и где-то до 250 - просто виснет (долго очень думает, я так и не дождался результат. Если же больше 250 - даже не компилируется, сразу кидает ошибку, что мало памяти. А все (на сколько я понимаю) из-за двумерного массива.
Вот мои две процедуры:
Это рандом, который по заданому n генерирует число из n цыфр:
Procedure rndm(n1, n2: integer);
var i,temp: integer;
f: text;
begin
randomize;
assign(f, 'c:\in.txt');
rewrite(f);
writeln(f, n1);
writeln(f, n2);
temp:= 0;
while temp = 0 do
temp:= random(9);
write(f, temp,' ');
for i:= 2 to n1 do
write(f, random(9),' ');
writeln(f);
temp:= 0;
while temp = 0 do
temp:= random(9);
write(f, temp,' ');
for i:= 2 to n2 do
write(f, random(9),' ');
close(f);
end;
И вторая, это уже само умножение:
Procedure umnoj;
var f,g: text;
i,j,k,l,x,y,p,s: integer;
a,a1,b,b1: array [1..max] of byte;
c: array [1..max,1..max] of byte;
go_on: boolean;
begin
assign(f, 'c:\in.txt');
assign(g, 'c:\out.txt');
reset(f);
rewrite(g);
for k:= 1 to max do
begin
a[k]:= 0;
a1[k]:= 0;
b[k]:= 0;
b1[k]:= 0;
end;
for k:= 1 to max do
for l:= 1 to max do
c[k,l]:= 0;
readln(f, i);
readln(f, j);
for k:= 1 to i do
read(f, a1[k]);
for k:= 1 to j do
read(f, b1[k]);
for k:= 1 to max do
begin
a[max-i+k]:= a1[k];
a1[k]:= 0;
end;
for k:= 1 to max do
begin
b[max-j+k]:= b1[k];
b1[k]:= 0;
end;
p:= 0;
s:= 0;
for l:= max downto 1 do
begin
for k:= max downto 1 do
begin
p:= a[k]*b[l]+p;
c[k-s,max-l+1]:= p mod 10;
p:= p div 10;
end;
inc(s);
end;
for l:= max downto 1 do
begin
a1[l]:= 0;
for k:= 1 to max do
a1[l]:= a1[l]+c[l,k];
end;
go_on:= true;
l:= max;
p:= 0;
while go_on do
begin
a1[l]:= a1[l]+p;
p:= a1[l] div 10;
a1[l]:= a1[l] mod 10;
dec(l);
go_on:= not ((p=0) and (a1[l]=0));
end;
for l:= 1 to max do
write(g, a1[l]);
close(f);
close(g);
end;
главная программа:
var n1,n2: integer;
begin
write('Vvedite dlinnu 1 chisla: ');
readln(n1);
write('Vvedite dlinnu 2 chisla: ');
readln(n2);
rndm(n1, n2);
umnoj;
end;
Не пойму что может быть не так :?
Автор: DriftKing 13.12.2007, 1:13
Еще забыл,
const max=10; // это максимальная длинна всех массивов.
при 10 все окей, при выше (на >20 точно не работает) нет.
Автор: Eternalko 13.12.2007, 1:37
Ну так не надо динамического сделай статический
Автор: Седрик 13.12.2007, 2:47
(eternalko)
Не знаю на каком это языке
Экспромт
//0.КОД И КАММЕНТЫ ЧИТАТЬ ПО ЦИФРАМ!!!! По номерам.
a=new Array; //1. Создаем наш 2Д массив. По трад. будет. а
getIntToArray(a);//2. Заносим туда нашу матрицу. Твоя табличка сложения
funnction sum(array a) //3. Функция, которая как-бы производит сумму этого столбика:)
{
res=new Array; //4.Это наш результат. Будущий) ВАЖНО! Пишу задом наперед!!!! См. каммент №16
int tmp; //5.Для помощи. Тут храниться сумма одного столбика
int k=0,l=0; //6. Доп. переменные. К. счетчик.
for(i=a.getLenght;i>0;i--) //7. "Ставим" "себя" в прав. угол. a.getLenght это ДЛИННА массива. Просто число!
{
while(tmp) //11.Пока тмп больше "0". Будем записывать число за числом из результата нашего столбца в массив. Десяток за десятком
{
l=k; //12. Тут l будет нашим счетчиком чтоб не k "портить".
res[l]=+tmp % 10; //13. Записывам(добавляем) еще один десяток
l++; //14. увеличиваем, чтоб след. десяток. добавить....
tmp=tmp/10; //15. уменьшаем tmp на 10. На посл. цифру котор. занесли в результат.
}
k++; //16. увелич. счетчик эл-та рез-та.
for(j=a.getHeight;j>0;j--) //8. Теперь в нижн. прав. угол.
{
tmp+=a[j][i]; //9. Снизу(!) вверх суммируем ВСЕ числа. Сумма столбика:)
}
}
return reverse(res);//17. Возвращаем наш результат. Вот он супер массив число. Только надо обернуть его, чтоб правильно записалось:)
}
sum(a);^_0
это С
Автор: FalseNegative 13.12.2007, 11:49
(eternalko)
А... И еще все переменные должны быть по нулям

В начале программы)
В C - да, в Паскале, - нет, никто никаких неявных присвоений 0 не делает!
(долго очень думает, я так и не дождался результат. Если же больше 250 - даже не компилируется, сразу кидает ошибку, что мало памяти. А все (на сколько я понимаю) из-за двумерного массива.
А дебаггером что, религия пользоваться не позволяет? Хотя сильно подозреваю, что всё дело именно в том, что мой способ (с переменной go_on работает правильно только если доступно больше индексов, чем надо. Иначе он почти наверняка пойдёт на 0, -1, и т.д. индексы.). ((10-значное*10значное) - это наверняка минимум 11-значное число.)
По нехватке памяти... Есть такое ограничение на нединамические массивы и строки, со времён TP. 255 и баста!
begin
a1[l]:= a1[l]+p;
p:= a1[l] div 10;
a1[l]:= a1[l] mod 10;
dec(l);
go_on:= l=0;
end;
Автор: Eternalko 13.12.2007, 13:45
А с этим кодом что?
(eternalko)
program arraysum;
var tosum: array [1...,1...] of Integer; //Почему он должен быть определен?? Вдруг числа оч. большие:)))
actualwidth,actualheight,colsum,k,l: Integer;
aresult: array [1..100] of Integer;
begin
for i := actualwidth downto 1 do
begin
while colsum do
begin
l:=k;
aresult[l]:=aresult[l]+colsum mod 10;
colsum:=colsum div 10
l:=l+1;
end;
k:=k+1;
for j:= actualheight downto 1 do
begin
colsum:=colsum+tosum[j,i];
end;
end;
end;
Автор: DriftKing 13.12.2007, 15:23
FalseNegative, да при го_он 1=0 тоже все работает. Но проблемы не решает. Прога как висла так и виснет, когда массив стает >20 знаков. И зацикливается именно этот фор:
for k:= 1 to max do
begin
a[max-i+k]:= a1[k];
a1[k]:= 0;
end;
Почему оно зацикливается при массиве с максим. кол-вом елементов 20 и выше, а при 10 и ниже - нет?.
Дебагер юзал, без толку. Увидел только где зацикливается и все.
Автор: DriftKing 13.12.2007, 15:25
Да...этот фор - это я прижимаю число к правому краю, ибо сразу оно записывает к левому.
Автор: Onami 13.12.2007, 15:55
Я так понимаю, у вас до сих пор траблы? Вот Кнут зачем писал книгу свою? Правильно, чтоб не лазили по пекабфорумам в поисках ответов!
NB: пользуйтесь лупой. 8)
По-моему, сопровождать алгоритм кодом на ЯВУ не нужно.
Автор: DriftKing 13.12.2007, 16:01
Яву? Где сдесь была ява? или я не в теме?
Автор: Onami 13.12.2007, 16:20
Яву?
Убило

Валялсо
ЯВУ - Язык Высокого Уровня. А Java - это от лукавого.
Автор: FalseNegative 13.12.2007, 16:50
(DriftKing)
FalseNegative, да при го_он 1=0 тоже все работает. Но проблемы не решает. Прога как висла так и виснет, когда массив стает >20 знаков. И зацикливается именно этот фор:
for k:= 1 to max do
begin
a[max-i+k]:= a1[k];
a1[k]:= 0;
end;
Почему оно зацикливается при массиве с максим. кол-вом елементов 20 и выше, а при 10 и ниже - нет?.
Дебагер юзал, без толку. Увидел только где зацикливается и все.

А Watch на k, a, a1 ставил? Нет никаких чудных изменений? (чувствую, где-то память испорчена...)
PS: неправильно такие имена переменных юзать. Ты же не говоришь Э! Ыыы. Я Тй. кртк. с. тлнт, тёщ. гон-ра. Зо оч бтр пчт мно.
Автор: FalseNegative 13.12.2007, 16:51
(Onami)
А Java - это от лукавого.
:shock: А я ей ем...
Автор: Eternalko 13.12.2007, 23:53
Проверьте мой код
Мне интересно, работает иль нет
Автор: DriftKing 14.12.2007, 17:18
А ты его с головы писал? Я не пойму, колсум это что? перенос? т.е. принимает значения 0 или 1? почему цыкл пока колсум?
а еще меня эта строка смущает немного: aresult[l]:=aresult[l]+colsum mod 10;
Но помоему работать не будет из-за "while colsum do ..."
Автор: Eternalko 14.12.2007, 21:21
(DriftKing)
А ты его с головы писал? Я не пойму, колсум это что? перенос? т.е. принимает значения 0 или 1? почему цыкл пока колсум?
а еще меня эта строка смущает немного: aresult[l]:=aresult[l]+colsum mod 10;
Но помоему работать не будет из-за "while colsum do ..."
Да. С головы. Это первая прогаа паскале :oops:
Можеет так понятней будет
program arraysum;
var tosum: array [1..100,1..100] of Integer;
actualwidth,actualheight,colsum,k,l: Integer;
aresult: array [1..100] of Integer;
begin
for i := actualwidth downto 1 do
begin
for j:= actualheight downto 1 do
begin
colsum:=colsum+tosum[j,i];
end;
while colsum do
begin
l:=k;
aresult[l]:=aresult[l]+colsum mod 10;
colsum:=colsum div 10
l:=l+1;
end;
k:=k+1;
end;
end;
Внешний for который идет по i перебирае КАЖДЫЙ СТОЛБЕЦ. Колонну

colsum это ColumnSumm. Сумма чисел в каждой колонне.
Допустим она большая и равна не просто 3, а скажем 72453. Тогда мы не можем просто записать тройку а все остальное откинуть

Надо каждый разряд отделить и отдельно дописать в след. эл-т матрицы результата
While colsum это цикл, который по разрядам толкает. Пока не растолкает(While colsum aka While colsum >0

)Не успокоится
А че строка смущает я не знаю
Может так не будет
aresult[l]:=aresult[l]+(colsum mod 10);
Ps. в проге есть маленький жук)
Пока не правил, чтоб понятней было о чем речь
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)