Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Делфи _ Деление двух длинных чисел

Автор: serogan 2.02.2007 22:11

В FAQ'е (длинная арифметика) нашла функции для деления двух длинных чисел. Можете объяснить, как реализовать это в Delphi, желательно как объекты? Заранее спасибо. smile.gif

Автор: volvo 2.02.2007 23:48

Здесь: http://forum.pascal.net.ru/index.php?s=&showtopic=2428&view=findpost&p=31907 что, НЕ объекты?

Вот тут было показано, как заставить этот модуль работать в Дельфи: http://forum.pascal.net.ru/index.php?s=&showtopic=15485&view=findpost&p=90166 (читаем до конца)

+ в http://forum.pascal.net.ru/index.php?showtopic=6361 тоже кое-что было по-моему, если хочешь - скачай, посмотри..

Автор: Гость 3.02.2007 3:42

Но в Hugeobj только умножение unsure.gif , деления нет (оно есть выше, но вроде не через объекты). А как можно переделать rolleyes.gif ?

Автор: Айра 3.02.2007 4:38

Мне тоже нужно это деление. Я нашла в DRKB модуль, начала компилировать, но в тех скобках, где есть HugeIntCarry возникает ошибка "Left side cannot be assigned to". Например:

procedure HugeInt_Inc(var a: HugeInt);
{ a := a + 1 }
var

i: Integer;
h: Word;
begin

i := 0;
h := 1;
repeat
h := h + a[i];
a[i] := Lo(h);
h := Hi(h);
Inc(i);
until (i > HugeIntMSB) or (h = 0);
HugeIntCarry := h > 0; // вот тут например
{$IFOPT R+ }
if HugeIntCarry then
RunError(215);
{$ENDIF}
end; { HugeInt_Inc }


Почему и как можно исправить?

Автор: volvo 3.02.2007 4:53

Цитата
Почему и как можно исправить?
Давай по-порядку:
1) "почему" - потому, что HugeIntCarry описывается, как типизированная константа (как видно, для совместимости с ранними версиями Паскаля, ведь в классическом Паскале нельзя описать переменную, и сразу же ей присвоить начальное значение, это возможно только с типизированной константой), а в Дельфи по умолчанию, константа - она и есть константа, в смысле, постоянная...

2) а вот теперь - "как исправить"... Очень просто, включить разрешение менять типизированные константы во время работы программы... Или в настройках проекта: "Project -> Options -> вкладка Compiler -> поставить галку на Assignable Typed Constants", или (что предпочтительнее - ибо не надо лазить по настройкам) первой строкой модуля:
{$J+}
// А дальше - без изменений

... И будет тебе счастье rolleyes.gif

Автор: Айра 3.02.2007 5:10

Спасибо, volvo! Все откомпилировалось.

Автор: volvo 3.02.2007 7:05

Цитата(Гость @ 2.02.2007 22:42)
деления нет (оно есть выше, но вроде не через объекты). А как можно переделать rolleyes.gif ?

Вот так попробуй:
Прикрепленный файл  DLINNA.PAS ( 6.76 килобайт ) Кол-во скачиваний: 597


Файл D.IN содержит:
Цитата
2785600000000
354


Тестовая программа:
program Project1;

{$APPTYPE CONSOLE}

uses
SysUtils, Dlinna;

var
a, b, c, d: TObj;
f_out: text;

begin
{ TODO -oUser -cConsole Main : Insert code here }

assign(input,'d.in');reset(input);
assign(f_out, 'd.txt');rewrite(f_out);

a.Init; b.Init; c.Init; d.Init;

a.ReadLong(input);
a.WriteLong(f_out);
b.ReadLong(input);
b.WriteLong(f_out);
c.DivLongTwo(a,b,d);
writeln(f_out, 'results:');
c.WriteLong(f_out);
d.WriteLong(f_out);

close(f_out);
close(Input);

a.Done; b.Done; c.Done; d.Done;
end.


Автор: Айра 3.02.2007 7:47

volvo, мне кажется, вы уже поняли, кто был гостем wink.gif wub.gif
Не смейтесь, но я не знаю где создать файл с расширение in...
Я попробовала добавить код из DRKB, но у меня не получилось его использовать wink.gif, а HugeObj добавила нормально.
В общем, я опять прошу о помощи...


p.s. не... посмеяться надо мной все-так нужно)))

Автор: volvo 3.02.2007 8:27

Цитата
мне кажется, вы уже поняли, кто был гостем
Естественно, у меня IP адреса перед глазами smile.gif

Цитата
я не знаю где создать файл с расширение in...
В папке с проектом... В принципе, это важно только для EXE-файла, так что будем говорить так: файл D.IN должен лежать там же, где лежит EXE-файл...

Прикрепить тебе проект полностью? (я не думаю, что теперь будут проблемы, это всего-навсего консольное приложение... smile.gif )

Автор: Айра 3.02.2007 8:37

Цитата
файл D.IN должен лежать там же, где лежит EXE-файл...

Это я поняла. Но расширение in я встретила впервые, и не знаю как сделать такой файл... позор)))...

А особых изменений в использовании dlinna по сравнению с HugeObj ведь нет, все также...

p.s. не по теме, а как вы делаете такие вещи типа "добавлено через ... минут"

Автор: volvo 3.02.2007 8:56

Цитата
Но расширение in я встретила впервые, и не знаю как сделать такой файл...
Я создавао обычный текстовый файл, и потом переименовывал (у меня расширения ни для каких типов файлов не скрываются, так что это совсем просто)... А в самом крайнем случае - создай любой TXT файл, только имя его укажи при Assign, какая разница, как он называться будет? smile.gif

Цитата
а как вы делаете такие вещи типа "добавлено через ... минут"
Теперь это делается автоматически, если ты добавляешь еще одно сообщение к своему же (именно добавляешь, т.е. отсылаешь еще один пост, а не редактируешь) в течении 20 минут (если Altair поменял, по умолчанию стояло 10 минут)

Автор: Айра 3.02.2007 9:01

Цитата
создай любой TXT файл

А я так делала. При работе программы был просто черный экран с мигающим курсором, ничего не выводилось ни вводилось(((

Добавлено через 2 мин.
Цитата(Айра @ 3.02.2007 5:01) *

А я так делала. При работе программы был просто черный экран с мигающим курсором, ничего не выводилось ни вводилось(((


Проверка smile.gif Нов целом я поняла как оно должно работать. Спасибо. А можно вы мне как-нибудь объясните сам техт модуля. Я не все в нем понимаю, а интересно rolleyes.gif

Автор: volvo 3.02.2007 9:06

1) Как называются у тебя входной/выходной файл?
2) Вот мой проект, попробуй - что выдаст в файле d.txt:
Прикрепленный файл  test.rar ( 3.15 килобайт ) Кол-во скачиваний: 431

Автор: Айра 3.02.2007 9:07


Еще раз спасибо! До свидания. Утро уже как ни как.

p.s. а цитаты все равно потом убирала, сразу не догадалась)))

Автор: Айра 3.02.2007 15:27

Входной я назвала d1.text, а выходной - d.text.
А теперь еще посмейся. Я тогда не догадалась, что нужно открыть и посмотреть свой выходной файл, думала результат на экране будет)))

В общем я все проверила. Работает. Вот что выдает:

Цитата
2785600000000
354
results:
7868926553 //целая часть
238 //остаток

Потом я во входном файле делала два больших числа.
И получила вот что:
Цитата
48600000000000000000000
200000000000
results:
243000005000 // по-моему программа ошиблась, или просто для двух больший чисел есть своя погрешноть...
4

Автор: volvo 3.02.2007 18:14

Нет... Просто я что-то не так портировал. Исходная программа (без объектов) считает как положено...

Сейчас проверю...

Автор: volvo 3.02.2007 18:31

Да, так и есть... Модуль, строка №242 -

         ost:=c;

заменить на
        ost.X^:=c.X^;

(с объектами первая форма не проходит...) smile.gif

Дельфи запускать лень, но в FPC (в режиме совместимости с Дельфи) работает как положено yes2.gif

Автор: Айра 4.02.2007 4:12

Спасибо! Я исправила.

Теперь у меня такой вопрос. Мои длинные числа (это факториалы вычисленные с помощью HugeObj) имеют тип TLargeInt. Числа в dlinna имеют тип TObj. Компил-р пишет, что типы не совместимы. Как можно это исправить?

Автор: volvo 4.02.2007 13:39

Убрать использование TLargeInt и пользоваться только TObj, или наоборот, убрать TObj, и пользоваться только TLargeInt... Эти 2 типа несовместимы и не будут... Пользуйся только одним из двух модулей...

Показать, как вычисляется факториал с использованием TObj?

Автор: Айра 4.02.2007 18:41

Буду пользоваться dlinna.

Цитата
Показать, как вычисляется факториал с использованием TObj?

Было бы неплохо. Я пыталась переделать функцию из HugeObj, но думаю одной сменой типа не обойтись smile.gif

И еще... В HugeObj для того, чтобы можно было выводить результат в memo (ввиде текста) Алена дала мне функцию Function HugeToStr: String. В dlinna наверно тоже что-то такое нужно добавить?

Автор: volvo 4.02.2007 19:08

Это - не метод объекта, просто процедура, описанная в Interface - части модуля (чтобы иметь к ней доступ извне), так же, как и та, что присутствует в HugeObj ...

{ A := n! }
procedure Fact(Var A: TObj; n: LongInt);
var T: TObj; i: LongInt;
begin
T.Init;

{
Вот это, конечно не очень красиво, надо бы как-то сделать
инициализацию TObj обычным числом... Но работает...
}
T.X^[1] := 1;
T.X^[0] := 1;

for i := 2 to n do begin
A.MulLongShort(T, i);
T.X^ := A.X^;
end;
end;



Цитата
В HugeObj для того, чтобы можно было выводить результат в memo (ввиде текста) Алена дала мне функцию Function HugeToStr: String. В dlinna наверно тоже что-то такое нужно добавить?
А можно, я за нее? rolleyes.gif

Опять же, аналогично тому, что делается в WriteLong, только вывод - не в файл, а в строку...
{ А вот это - уже метод объекта, не забывай его описание добавить в Type TObj }
Function TObj.HugeToStr: String;
var ls,s:string;
i:integer;
begin
result := '';
str(_osn div 10, ls);
result := result + IntToStr(X^[X^[0]]);
for i:=X^[0]-1 downto 1 do
begin
str(X^[i],s);
while length(s)<length(ls) do s:='0'+s;
result := result + s;
end;
end;

Автор: Айра 4.02.2007 20:14

Спасибо!!!

Цитата
А можно, я за нее?

Конечно smile.gif

Я правильно дабовила?
type
Tlong=array[0 .. _maxdig]of integer;
Plong=^Tlong;

TObj = object
Constructor Init;
Destructor Done;

Function HugeToStr: String; // вот тут?

procedure ReadLong(var f:text);
procedure WriteLong(var f:text);

...

private
X: PLong;
end;

procedure Fact(Var A: TObj; n: LongInt); // и вот тут?


Все компилируется, но при работе выдает ошибку "Нарушение прав доступа в адресе 00402fc8 в модуле 'uchebnik.exe'. Напишите из адреса 00000000'." и выделяет эту строку (модуль HugeObj я удалила из проекта):
procedure TForm12.Button2Click(Sender: TObject);
var n: longint;
per: TObj;
begin
if edit4.text='' then
begin
MessageBeep(MB_ICONHAND);
ShowMessage('Не заданы значения!');
end
else
begin
memo1.Text:='';
n:=StrToInt(edit4.Text);
if n>524 then ShowMessage('Невозможно вычислить для данного числа! Приносим свои извинения.')
else
begin
Fact(per, n);
memo1.Text:=per.HugeToStr; //эту
end;
end;
end;


Я опять сделала что-то неправильно?

Автор: volvo 4.02.2007 20:25

Цитата
Я опять сделала что-то неправильно?
yes2.gif Забыла инициализировать переменную Per...

Добавлено через 1 мин.
begin
per.Init;
Fact(per, n);

memo1.Text := per.HugeToStr;
end;

Автор: Айра 5.02.2007 1:05

Цитата
Забыла инициализировать переменную Per...

wink.gif unsure.gif

Сделала процедуру с делением. Воть:
procedure TForm12.Button3Click(Sender: TObject);
var m,n: longint;
f1,f2,ost,raz: TObj;
begin
if (edit5.text='') or (edit6.text='') then
begin
MessageBeep(MB_ICONHAND);
ShowMessage('Не заданы значения!');
end
else
begin
memo2.Text:='';
m:=StrToInt(edit5.Text);
n:=StrToInt(edit6.Text);
f1.Init; f2.Init; ost.Init; raz.Init;
fact(f1, m);
fact(f2, m-n);
raz.DivLongTwo(f1,f2,ost);
memo2.text:=raz.HugeToStr;
end;
end;


Только если просто считать факториалы от 0 или 1 опять будет "access violation at address 0046ECE in module ... Read of address 02C0FFFC" и выделится эта строка в модуле dlinna

Function TObj.HugeToStr: String;
var ls,s:string;
i:integer;
begin
result := '';
str(_osn div 10, ls);
result := result + IntToStr(X^[X^[0]]);
for i:=X^[0]-1 downto 1 do
begin
str(X^[i],s); //эта
while length(s)<length(ls) do s:='0'+s;
result := result + s;
end;
end;

а если делить их друг на дружку будет считать неправильно(((

Мне надо прописать эти варианты (if n=0 then ...) или можно сделать по-другому?






Автор: volvo 5.02.2007 1:24

Добавить строку в Fact:

{ A := n! }
procedure Fact(Var A: TObj; n: LongInt);
var T: TObj; i: LongInt;
begin
T.Init;
T.X^[1] := 1;
T.X^[0] := 1;

for i := 2 to n do begin
A.MulLongShort(T, i);
T.X^ := A.X^;
end;
A.X^ := T.X^; // <-- Вот эту !!!

end;

(просто когда цикл не выполняется ни разу, переменная A остается, в смысле - оставалась, неизменной, а это плохо)

Автор: Айра 5.02.2007 2:35

volvo, спасибо тебе огромное!!! give_rose.gif wub.gif give_rose.gif


Я наконец-то доделала свою программу! Ура yahoo!.gif


p.s. специфика русского человека - делать все в последний момент (завтра мне сдавать эту работу))))