Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 08.07.2010, 00:35
Аватар для PhoeniX
PhoeniX PhoeniX вне форума
Always hardcore!
 
Регистрация: 04.03.2009
Адрес: СПб
Сообщения: 3,239
Версия Delphi: GCC/FPC/FASM
Репутация: 62149
По умолчанию Оптимизировать код

Накидал модуль, для преобразования чисел между системами счисления с основаниями 2 и 10.

Работает хорошо, но очень медленно... Как можно его оптимизировать?
И ещё, если я что-то упустил, поправьте места, где могут возникать ошибки...

Код:
unit uDecBinConvert;

interface

type
  TBit = 0..1;
  TDecimal = 0..9;
  TBitArray = array of TBit;
  TDecArray = array of TDecimal;

function Dec2Bin (dec: string): string;
function Bin2Dec (bin: string): string;

implementation

uses Classes, SysUtils;

procedure StrToBinArr(s: string; var bar: TBitArray);
  function CharToBit (c: char): TBit;
  begin
    if c = '0' then Result:=0 else
    if c = '1' then Result:=1 else
    raise (Exception.Create('Invalid character: '''+c+''''));
  end;
var
  i:integer;
begin
  while (Length(s)>0)and(s[1] in [#10,#13,#32,#9]) do Delete(s,1,1);
  while (Length(s)>0)and(s[Length(s)] in [#10,#13,#32,#9]) do Delete(s,Length(s),1);
  SetLength(bar,Length(s));
  for i:=1 to Length(s) do
    bar[Length(s)-i]:=CharToBit(s[i]);
end;

procedure StrToDecArr(s: string; var bar: TDecArray);
  function CharToDec (c: char): TDecimal;
  begin
    if (c>=#48) and (c<=#58) then
      Result:=ord(c)-48
    else
      raise (Exception.Create('Invalid character: '''+c+''''));
  end;
var
  i:integer;
begin
  while (Length(s)>0)and(s[1] in [#10,#13,#32,#9]) do Delete(s,1,1);
  while (Length(s)>0)and(s[Length(s)] in [#10,#13,#32,#9]) do Delete(s,Length(s),1);
  SetLength(bar,Length(s));
  for i:=1 to Length(s) do
    bar[Length(s)-i]:=CharToDec(s[i]);
end;

procedure DecArrToStr(dar: TDecArray; var s: string);
  function DecToChar (d: TDecimal): char;
  begin
    Result:=chr(48+d);
  end;
var
  i:integer;
begin
  s:='';
  for i:=1 to Length(dar) do
    s:=s+DecToChar(dar[Length(dar)-i]);
end;

procedure BinArrToStr(bar: TBitArray; var s: string);
  function BinToChar (d: TBit): char;
  begin
    Result:=chr(48+d);
  end;
var
  i:integer;
begin
  s:='';
  for i:=1 to Length(bar) do
    s:=s+BinToChar(bar[Length(bar)-i]);
end;

procedure IncDecimal(var d: TDecArray);
var
  flag: boolean;
  index: integer;
begin
  flag:=false;
  index:=0;
  while not flag do begin
    if Length(d)<index+1 then begin
      SetLength(d,Length(d)+1);
      d[index]:=0;
    end;
    if d[index]=9 then begin
      d[index]:=0;
      inc(index)
    end else begin
      inc(d[index]);
      flag:=true;
    end;
  end;
end;

procedure DecDecimal(var d: TDecArray);
var
  flag: boolean;
  index: integer;
begin
  flag:=false;
  index:=0;
  while not flag do begin
    if d[index]=0 then begin
      d[index]:=9;
      inc(index)
    end else begin
      dec(d[index]);
      flag:=true;
    end;
  end;
  while (Length(d)>0)and(d[Length(d)-1]=0) do SetLength(d,Length(d)-1);
end;

procedure IncBinary(var b: TBitArray);
var
  flag: boolean;
  index: integer;
begin
  flag:=false;
  index:=0;
  while not flag do begin
    if Length(b)<index+1 then begin
      SetLength(b,Length(b)+1);
      b[index]:=0;
    end;
    if b[index]=0 then begin
      b[index]:=1;
      flag:=true;
    end else begin
      b[index]:=0;
      inc(index);
    end;
  end;
end;

procedure DecBinary(var b: TBitArray);
var
  flag: boolean;
  index: integer;
begin
  flag:=false;
  index:=0;
  while not flag do begin
    if b[index]=1 then begin
      b[index]:=0;
      flag:=true;
    end else begin
      b[index]:=1;
      inc(index);
    end;
  end;
  while (Length(b)>0)and(b[Length(b)-1]=0) do SetLength(b,Length(b)-1);
end;

function Dec2Bin (dec: string): string;
var
  BinArr: TBitArray;
  DecArr: TDecArray;
begin
  SetLength(BinArr,0);
  SetLength(DecArr,0);
  StrToDecArr(dec,DecArr);
  while Length(DecArr)>0 do begin
    DecDecimal(DecArr);
    IncBinary(BinArr);
  end;
  BinArrToStr(BinArr,Result);
end;

function Bin2Dec (bin: string): string;
var
  BinArr: TBitArray;
  DecArr: TDecArray;
begin
  SetLength(BinArr,0);
  SetLength(DecArr,0);
  StrToBinArr(bin,BinArr);
  while Length(BinArr)>0 do begin
    IncDecimal(DecArr);
    DecBinary(BinArr);
  end;
  DecArrToStr(DecArr,Result);
end;

end.
Прилагаю исходник, и пример пользования...
Вложения
Тип файла: rar DecBinConvert.rar (3.9 Кбайт, 3 просмотров)
__________________
Оставайтесь хорошими людьми...
VK id2634397, ds [at] phoenix [dot] dj

Последний раз редактировалось PhoeniX, 08.07.2010 в 00:38.
Ответить с цитированием
  #2  
Старый 08.07.2010, 00:53
Аватар для Rokuell
Rokuell Rokuell вне форума
Активный
 
Регистрация: 27.12.2006
Адрес: Псков
Сообщения: 274
Версия Delphi: Delphi 7
Репутация: 497
По умолчанию

Эмм.. если честно, то лень сейчас разбирать чужой код, но если тебе интересна эта тема, то выкладываю исходник для преобразования чисел из одной системы счисления в другую, исходная и конечная система счисления должны находиться в диапазоне [2..36].
Написано в далёком 2006 и имеет пару ошибок, вроде переполнения...
Вложения
Тип файла: zip Перевод чисел.zip (4.8 Кбайт, 6 просмотров)
__________________
Велик и могуч наш Object Pascal !
ICQ: 357-591-887
Ответить с цитированием
  #3  
Старый 08.07.2010, 02:53
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,087
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Думаю:
Код
Код:
  while (Length(s)>0)and(s[1] in [#10,#13,#32,#9]) do Delete(s,1,1);
  while (Length(s)>0)and(s[Length(s)] in [#10,#13,#32,#9]) do Delete(s,Length(s),1);
можно заменить на:
Код:
for i := Length(s) DownTo 1 Do
  If Not (s[i] In ['0'..'9']) Then Delete(s,i,1);
По ощущениям должно быть быстрее и работать правильнее.
Тогда функция CharToDec примет вид:
Код:
function CharToDec (c: char): TDecimal;
begin
   Result:=ord(c)-48
end;
и ее можно сделать inline (или просто перенести код в место вызова), что еще убыстрит в конкретном месте.

И вообще, кому-то я тут писал код, который некоторое число конвертит в битовую строку и обратно. Кстати, даже с некоторой упаковкой по сравнению с твоим кодом. Правда, это была не честная конвертация, а для передачи данных в битовом образе.
Ответить с цитированием
  #4  
Старый 08.07.2010, 13:16
Аватар для PhoeniX
PhoeniX PhoeniX вне форума
Always hardcore!
 
Регистрация: 04.03.2009
Адрес: СПб
Сообщения: 3,239
Версия Delphi: GCC/FPC/FASM
Репутация: 62149
По умолчанию

Я уже сказал, что это мне не подходит.

Про замечания знаю, но это не особо ускорит сам процесс преобразования. Мне надо бы как-либо ускорить код функций IncBinary, IncDecimal, DecBinary и DecDecimal... Я уже думал просмотреть код в ассемблере, и переписать функцию на нём...
__________________
Оставайтесь хорошими людьми...
VK id2634397, ds [at] phoenix [dot] dj
Ответить с цитированием
  #5  
Старый 08.07.2010, 14:17
Аватар для dr. F.I.N.
dr. F.I.N. dr. F.I.N. вне форума
I Like it!
 
Регистрация: 12.12.2009
Адрес: Россия, г. Новосибирск
Сообщения: 663
Версия Delphi: D6/D7
Репутация: 26643
По умолчанию

DJ PhoeniX, а зачем ты так заморачиваешься с типами TBit, TDec? Один хрен размер = 1 байт И работать проще. Суть конечно ясна, но ведь есть и готовые методы решения твоей задачи. Поясни суть и нюансы твоей, если я чего-то не понимаю
Ответить с цитированием
  #6  
Старый 08.07.2010, 14:37
Аватар для PhoeniX
PhoeniX PhoeniX вне форума
Always hardcore!
 
Регистрация: 04.03.2009
Адрес: СПб
Сообщения: 3,239
Версия Delphi: GCC/FPC/FASM
Репутация: 62149
По умолчанию

Мне нужна быстрая работа с числами ЛЮБЫХ размеров, а всё готовые методы ограничены в пределах Integer, максимум Int64...
__________________
Оставайтесь хорошими людьми...
VK id2634397, ds [at] phoenix [dot] dj
Ответить с цитированием
  #7  
Старый 08.07.2010, 21:03
Аватар для dr. F.I.N.
dr. F.I.N. dr. F.I.N. вне форума
I Like it!
 
Регистрация: 12.12.2009
Адрес: Россия, г. Новосибирск
Сообщения: 663
Версия Delphi: D6/D7
Репутация: 26643
По умолчанию

Вот. Совместил в одной программе твой модуль и свой ... Результат превосходит все ожидания... Хотя и не самый оптимал...еще можно улучшать и улучшать! Хотя скорости и так хватает и размер числа ограничен стрингом

З.Ы. число в 500 символов конвертится за 187мс (из 10 в 2), 3000 за 7сек. а обратно за 343 мс и 16сек соответственно. Твой метод умирает уже на 8-10 символах.
З.З.Ы. Сильно не критиковать...вобще ничего не оптимизировал...думаю, поработав еще чуток, можно и мой результат улучшить в разы.

Последний раз редактировалось dr. F.I.N., 12.01.2012 в 17:09.
Ответить с цитированием
  #8  
Старый 08.07.2010, 22:27
Аватар для PhoeniX
PhoeniX PhoeniX вне форума
Always hardcore!
 
Регистрация: 04.03.2009
Адрес: СПб
Сообщения: 3,239
Версия Delphi: GCC/FPC/FASM
Репутация: 62149
По умолчанию

Бл... *цензура*...
Как я сразу не допёр до этого решения... *i'm looser, epic fail *
Лови + в репутацию...
__________________
Оставайтесь хорошими людьми...
VK id2634397, ds [at] phoenix [dot] dj
Ответить с цитированием
  #9  
Старый 09.07.2010, 07:01
Аватар для dr. F.I.N.
dr. F.I.N. dr. F.I.N. вне форума
I Like it!
 
Регистрация: 12.12.2009
Адрес: Россия, г. Новосибирск
Сообщения: 663
Версия Delphi: D6/D7
Репутация: 26643
По умолчанию

А вообще, я бы попробывал взять класс для работы с очень длинными числами и оптимизировать его под твою задачу (сложение, деление на 2, степень 2). А учитывая, что есть реализации на асме - вообще можно очень шустро все реализовать.
Ответить с цитированием
  #10  
Старый 09.07.2010, 10:26
Аватар для PhoeniX
PhoeniX PhoeniX вне форума
Always hardcore!
 
Регистрация: 04.03.2009
Адрес: СПб
Сообщения: 3,239
Версия Delphi: GCC/FPC/FASM
Репутация: 62149
По умолчанию

Очень длинными - это какими? Самый "большой" формат, который я знаю - это int64, но он ограничен достаточно небольшой длиной... А мне нужно обрабатывать числа длиной до 256 цифр.
__________________
Оставайтесь хорошими людьми...
VK id2634397, ds [at] phoenix [dot] dj
Ответить с цитированием
  #11  
Старый 09.07.2010, 13:03
Аватар для dr. F.I.N.
dr. F.I.N. dr. F.I.N. вне форума
I Like it!
 
Регистрация: 12.12.2009
Адрес: Россия, г. Новосибирск
Сообщения: 663
Версия Delphi: D6/D7
Репутация: 26643
По умолчанию

Вчера дома находил класс реализующий очень длинные числа...но сегодня с работы не могу вспомнить какой запрос построил Вечером гляну дома по журналу.
На данный момент нашел набор функций. Но лично мне он не нравится.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 07:47.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025