Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 31.05.2011, 06:30   #1
cr1me
Пользователь
 
Регистрация: 04.01.2011
Сообщений: 10
По умолчанию Длинная Арифметика. Деление.

Здравствуйте. Мне была поставлена задача организовать деление очень длинного целого не отрицательного числа на короткое целое.
в идеале нужно было сделать через строки но у меня не вышло.
после прочтения книжки Окулова о Длинной арифметике нарисовался вот такой код.
Код:
  
Const
  base = 1000;
  baselen = 3;
Type
  TLong = array[0..100] of integer;
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
function WriteLong(Var x: TLong):string;
Var i: integer;
    s: string;
Begin
  For i := x[0] - 1 downto 1 do
  Begin
    s := inttostr(x[i]);
    While(length(s) < baselen) do s := '0' + s;
  End;
  result:=s;
End;
Function ReadLong(s:string):TLong;
Var
x: TLong;
i, j, k: integer;
Begin
  While (length(s) mod baselen <> 0) do s := '0' + s; //Добавляем строке ведущие нули, чтобы в каждом элементе массива было ровно baselen цифр.
  Fillchar(x, sizeof(x), 0); //Опустошаем наше число.
  x[0] := length(s) div baselen; //Просчитываем длину числа.
  k := 0;
  For i := x[0] downto 1 do
  begin
    For j := 1 to baselen do
    begin
      inc(k);
      x[i] := x[i] * 10 + strtoint(s[k]);
    end;
  end;
  ReadLong := x;
End;
Function divlong(a: TLong; b: integer): TLong;
Var i, ost: integer;
Begin
  ost := 0;
  fillchar(result, sizeof(result), 0);
  For i := a[0] downto 1 do
  begin
    Result[i] := (a[i] + ost * base);
    ost := result[i] mod b;
    result[i] := result[i] div b;
  end;
  result[0] := a[0];
  while result[result[0]] = 0 do
    dec(result[0]);
End;
procedure TForm1.Button1Click(Sender: TObject);
var
q:tlong;
s1,s2:string;
begin
s1:=edit1.Text;
s2:=edit2.Text;
q:=readlong('5898');
form1.Caption:=writelong(q);
//q:=divlong(q,3);
не могу понять где ошибка... даже когда действия не выполняю,а просто считываю число функцией readlong и вывожу writelong выводятся девятки в количестве baselen = 3;
Помогите пожалуйста разобраться.
Криворукий Самоучка
cr1me вне форума Ответить с цитированием
Старый 31.05.2011, 06:58   #2
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Есть такой журнал ПРОграммист. В нем описана длинная арифметика, в том числе и деление чисел... Выпуски 12 и 13. Кроме того, там приложены исходники на Дельфи, которые обкатывались на данном форуме (мной). Поэтому их можно найти здесь (при желании и умении пользоваться поиском по данному форуму).
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 31.05.2011, 09:45   #3
cr1me
Пользователь
 
Регистрация: 04.01.2011
Сообщений: 10
По умолчанию

спасибо за ссылку на журнал, исходники я тоже нашел. но там так все реализованно что мне не поверят что это я сам делал=) при всем желании.
в поисках информации нашел вот это сообщение
Цитата:
Я реализовывал длинную арифметику в строках (скорость та еще, но мне было интересно). Умножение и деление по школьному, как в тетрадке без калькулятора
случайно не осталось исходничков? если не жалко поделитесь пожалуйста
Криворукий Самоучка
cr1me вне форума Ответить с цитированием
Старый 31.05.2011, 10:19   #4
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Вам же не поверят . Прочтите статью - там описаны принципы работы с длинной арифметикой. Если Вы поймете как это работает, то сможете написать сами...
На форуме и в журнале одни исходники (при условии если это их я выкладывал, вроде как еще кто-то этим занимался).
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 31.05.2011, 13:11   #5
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

FGInt: http://www.submanifold.be/triade/GInt/gint.html
BigInt: http://sourceforge.net/projects/bigint-dl/
Раньше ещё была NX здесь: http://www.ellipsa.eu/public/nx/nx.html , но её закрыли.
И в DeHL кажется была реализация.

P.S. Просмотрел, что надо самому. Отбой.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.

Последний раз редактировалось GunSmoker; 31.05.2011 в 13:15.
GunSmoker вне форума Ответить с цитированием
Старый 31.05.2011, 13:34   #6
cr1me
Пользователь
 
Регистрация: 04.01.2011
Сообщений: 10
По умолчанию

ну немного разобрался..пока вот так. ошибка в цикле while незнаю как правильно условие пока задать.(м.б пока остаток не станет меньше чем делитель?) и еще с остатком беда видимо. млин башка уже не варит
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
delimoe,delitel,res,ost:string;
i1,i2,s1,s2,stemp,x,q:integer;
begin

q:=0;
stemp:=0;
delimoe:=edit1.Text;
delitel:=edit2.text;
i1:=length(delimoe);
i2:=length(delitel);//zapominaem skol'ko razryadov-po stol'ko i budem otrivat' ot chisla 1
s1:=strtoint(edit1.Text);
s2:=strtoint(edit2.Text);
while q<>i1 do begin
q:=q+1;
for x:=1 to i2 do
  begin
stemp:=stemp+ strtoint(delimoe[x]); //poly4ili chislo kotoroe mi budem delit' na delitel' nado proverit' ne men'she li ono 4em delitel'
if stemp<s2 then stemp:=stemp+strtoint(delimoe[i2+1]);
 end;
//esli 4islo men'she napishem eshe 1 razryad.
//stemp teper' stemp soderjit chislo kotoroe mojno delit' na delitel'
 res:=res+inttostr(stemp div s2);// записали результат  нужно найти остаток от деления
 ost:=inttostr(stemp mod s2);  //записали остаток теперь к нему нужно прибавить след разряд
 end;
 form1.Caption:=res;
end;
это сугубо мысли набросанны, как понимаю нужно все это воедино сложить и в цикл засунуть
ход мыслей такой
1) узнать количество разрядов в делителе(допустим 2)
2) взять первые 2 разряда делимого(2)
3)проверить меньше ли первые 2 разряда делимого чем делитель
4) если меньше то переводим из строки в число и делим если нет то дописываем следующий разряд а потом уже делим.
получаем деление и остаток
5)деление записывает в результат(потом будем дополнять следующими числами)
6)к остатку добавляем 1 разряд делимого и сравниваем больше ли это число чем делитель и так продолжаем пока не кончатся разряды делимого
Криворукий Самоучка

Последний раз редактировалось cr1me; 31.05.2011 в 14:02.
cr1me вне форума Ответить с цитированием
Старый 01.06.2011, 07:18   #7
cr1me
Пользователь
 
Регистрация: 04.01.2011
Сообщений: 10
По умолчанию

все получилось. спасибо за ссылки на литературу. разобрался. выкладывать код не буду, как сказал товарищ уткин чтобы разобрались люди сами.
предпоследнего наброска и алгоритма мышления вполне достаточно.
кому сильно прижмет, как мне, стучите в жабу поделюсь кодом un1qum@jabber.ru
Криворукий Самоучка

Последний раз редактировалось cr1me; 01.06.2011 в 08:50.
cr1me вне форума Ответить с цитированием
Старый 01.06.2011, 08:51   #8
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

4-ый пункт - если в делимом меньше разрядов, чем в делители, то насколько я помню в результат нужно нуль дописывать...
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 28.05.2013, 12:13   #9
Carburn
Новичок
Джуниор
 
Регистрация: 02.10.2012
Сообщений: 1
По умолчанию

Правильный код
Код:
function TForm1.WriteLong(var x: TLong): string;
Var i: integer;
    s,v: string;

Begin
v:=inttostr((x[x[0]]));
  For i := x[0] - 1 downto 1 do
  Begin
    s := inttostr(x[i]);
    While(length(s) < baselen) do s := '0' + s;
    v:=v+s;
  End;
  result:=v;
End;
Carburn вне форума Ответить с цитированием
Старый 28.05.2013, 18:34   #10
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Carburn, а чего Вы не дождались пару дней, до того момента когда пройдет ровно год с момента последнего поста?
Это называется некропостинг - отвечать на давно умершие и не нужные ТС темы. В общем не надо этим заниматься
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Длинная арифметика : деление (числа в string'е на число 256) Dima_Dima Общие вопросы Delphi 6 06.02.2011 20:39
длинная арифметика: деление Dеlphi Общие вопросы C/C++ 0 19.01.2011 13:19
Длинная арифметика Khelleos Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 2 20.12.2010 09:08
Длинная арифметика на C#(деление) Mr_Dark Общие вопросы .NET 1 21.06.2009 21:57
Длинная арифметика: деление Vadik(R) Помощь студентам 1 27.03.2009 12:08