StrToInt на чистом паскале.

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Re: StrToInt на чистом паскале.

Сообщение Seenkao » 20.01.2022 15:38:54

Изначально я просто для себя создавал более быстрый вариант StrToInt. Взялся за доделку и одновременно на форумах Lazarus пошёл слушок, что у них поломался Val, и они его чинят/заменяют.
Вот я и решил тогда доделать до конца (ещё не до конца), а заодно и выложить для остальных.

По сути Val неплох. Это просто "модернизация" его.

wavebvg, не подойдёт для меня такая реализация.

Добавлено спустя 9 часов 54 минуты 47 секунд:
Тесты, по коду который скидывал zub.
Int32:
Val(), score: 3073
rejected: 0

TryChars2Int, score: 1486
rejected: 0

sc_StrToLongWord or sc_StrToInt, score: 1104
rejected: 0

Int64:
Val(), score: 3075
rejected: 0

TryChars2Int, score: 1627
rejected: 0

sc_StrToQWord or sc_StrToInt64, score: 1072
rejected: 0

Press any key to exit...


ну вот ещё маленькая модернизация. )))

Дольше всех просчитываются двоичные числа... надо другую технологию для них стряпать. Может когда-нибудь займусь.
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

Re: StrToInt на чистом паскале.

Сообщение Alexander » 21.01.2022 20:46:51

Такое впечатление, что не работает на отрицательных числах.

Код: Выделить всё
>mStrToInt h:19  m:34 s: 44
1234567899876543210
>fst.StrToInt h:19  m:34 s: 56
1234567899876543210
>StrToInt64 h:19  m:35 s: 14
1234567899876543210
>geStrToInt h:19  m:35 s: 32
1234567899876543210
>5 h:19  m:35


Код: Выделить всё
>mStrToInt h:19  m:37 s: 3
-1234567899876543210
>fst.StrToInt h:19  m:37 s: 14
-1234567899876543210
>StrToInt64 h:19  m:37 s: 32
-1234567899876543210
>geStrToInt h:19  m:37 s: 50
0
>5 h:19  m:3


teststrto.pas
Код: Выделить всё
{$MODE OBJFPC}
{$LONGSTRINGS ON}
//{$RANGECHECKS ON}

uses fst, sysutils, ge_external_utils in '../geStrToIntGIT/fast_StrToInt/geStrToInt/ge_external_utils.pas';

var
s : string = '-01234567899876543210';
f, tmp : Int64;
t : TSystemTime;

function mStrToInt(s : string) : Int64; register;
var f : Int64;
begin
result := 0;
if s[1] = '-' then begin
  for f := 2 to Length(s) do begin
  Result := Result * 10 + (byte(s[f])  - 48);
  end;
Exit(-Result);
end else begin
  for f := 1 to Length(s) do begin
  Result := Result * 10 + (byte(s[f])  - 48);
  end;
end;
end;

begin


GetLocalTime(t);
writeln('>mStrToInt h:', t.hour, '  m:',t.minute , ' s: ', t.second);
writeln(mStrToInt(s));

for f := 1 to 100000000 do mStrToInt(s);

GetLocalTime(t);
writeln('>fst.StrToInt h:', t.hour, '  m:',t.minute , ' s: ', t.second);
fst.StrToInt(PChar(s), tmp);
writeln(tmp);

for f := 1 to 100000000 do fst.StrToInt(PChar(s), tmp);

GetLocalTime(t);
writeln('>StrToInt64 h:', t.hour, '  m:',t.minute , ' s: ', t.second);
writeln(StrToInt64(s));

for f := 1 to 100000000 do StrToInt64(s);

GetLocalTime(t);
writeln('>geStrToInt h:', t.hour, '  m:',t.minute , ' s: ', t.second);
geStrToInt(s, tmp, isInt64);
writeln(tmp);

for f := 1 to 100000000 do geStrToInt(s,tmp,isInt64);

GetLocalTime(t);
writeln('>5 h:', t.hour, '  m:',t.minute , ' s: ', t.second);

end.


fst.pas

Код: Выделить всё
unit fst;

{$MODE OBJFPC}

interface

uses sysutils;

procedure StrToInt(AStr: PChar; out AResult: Int64);

implementation

procedure StrToInt(AStr: PChar; out AResult: Int64);
const
  MAX_VALUE = High(AResult) div 10;
  MAX_NUMER = High(AResult) mod 10;
  MAX_NNUMER = -Low(AResult) mod 10;
var
  n, o: SmallInt;
  p: PChar;
begin
  p := AStr;
  if p^ = #45 then
  begin
    n := 1;
    Inc(p);
  end
  else
    n := 0;
  if p^ = #0 then
    raise EConvertError.Create('Str empty');
  AResult := 0;
  repeat
    if (p^ >= #48) and (p^ <= #57) then
    begin
      o := Ord(p^) - 48;
      if (AResult >= MAX_VALUE) and (o > MAX_NUMER) then
        if (n = 0) or (o > MAX_NNUMER) then
          raise EConvertError.CreateFmt('"%s" is not valid integer', [AStr]);
      AResult := AResult * 10;
      AResult := AResult + o;
    end
    else
      raise EConvertError.CreateFmt('"%s" is not valid integer', [AStr]);
    Inc(p);
  until p^ = #0;
  if n = 1 then
    AResult := -AResult;
end;   

end.
Аватара пользователя
Alexander
энтузиаст
 
Сообщения: 690
Зарегистрирован: 18.12.2005 19:10:00
Откуда: оттуда

Re: StrToInt на чистом паскале.

Сообщение Seenkao » 23.01.2022 00:03:14

Alexander, там ведущий нуль, который показывает длину строки больше, чем она есть.
Думаю для отрицательных чисел переделаю чтоб можно было делать ведущие нули.

Для положительных... не знаю... тогда всё перепутается... У всех вызовет "кашу в голове". Ведущий нуль - это для не десятичных чисел...

Но для geStrToInt/geStrToUInt можно сделать исключение... надо определиться.

Благодарю за информацию!

Добавлено спустя 2 часа 50 минут 35 секунд:
Исправил, теперь ведущие нули удаляются в основных функциях всегда.
Для пользовательских функций:
sc_StrToByte, s_StrToByte, sc_StrToWord, s_StrToWord, sc_StrToLongWord, s_StrToLongWord, sc_StrToQWord и s_StrToQWord - не должны содержать ведущие нули для десятичной системы счисления.
Причина одна, функция ни когда не сможет узнать восьмеричная система или десятичная, если в числе будут содержаться цифры 0-7 и ни какие другие.
0 - обозначает восьмеричную систему (не я придумывал). Можно конечно сделать исключение, тогда ведущие нули будут автоматически из десятичного и из восьмеричного чисел убираться.

Возникает вопрос, что важнее: совместимость или возможность разделения по системам?
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

Re: StrToInt на чистом паскале.

Сообщение Alexander » 23.01.2022 22:21:27

Спасибо ! Теперь работает как надо.
Аватара пользователя
Alexander
энтузиаст
 
Сообщения: 690
Зарегистрирован: 18.12.2005 19:10:00
Откуда: оттуда

Re: StrToInt на чистом паскале.

Сообщение Seenkao » 25.01.2022 07:27:53

Alexander, не за что.
Но вот подобные правки потом выявляют неточности в коде, которые так же приходится править. )))
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

Re: StrToInt на чистом паскале.

Сообщение Seenkao » 31.01.2022 23:45:05

в файле конфигурации добавил возможность выбора "вида строки", на выбор:
Код: Выделить всё
{$DEFINE USE_STRING} // String
{$DEFINE USE_ANSISTRING} // AnsiString
{$DEFINE USE_UNICODESTRING} // UnicodeString
{$DEFINE USE_UTF8STRING} //UTF8String

Если в своём коде вы используете какой-то из видов строк, то лучше переключать дефайны. Иначе можно потерять в скорости из-за перевода строки из одного вида в другой.
Дефайны действуют в порядке приоритета сверху вниз. Нижние отключаться, если какой-то из верхних включен.

Так же мелкое исправление в коде, функция geStrToUInt (и все зависимые от неё) могли выдать ошибку при подсчёте.

Добавлено спустя 10 минут 22 секунды:
Вопрос поднимаемый уважаемым товарищем zub-ом. Надо ли делать функции, которые будут работать с массивом PChar? Они даже работают быстрее и там не надо будет менять дефайны для видов строк.
Просто для такой функции много лишней писанины в функцию. По мне просто не удобно.
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

Re: StrToInt на чистом паскале.

Сообщение zub » 31.01.2022 23:59:17

Строки нужны разные, а не какаято одна.
Основным должен быть вариант с (const PartStr:array of widechar/char) а не (const Str: AnsiString/UnicodeString)

Добавлено спустя 4 минуты 29 секунд:
Подсмотри уже как сделана интерфейсная часть у avk по ссылке выше
>>которые будут работать с массивом PChar
не с массивом, а с параметром открытый массив. их также надо char/widechar варианты

Добавлено спустя 3 минуты 42 секунды:
>>Просто для такой функции много лишней писанины в функцию. По мне просто не удобно.
Ты ошибаешся. этот вариант позволяет передать в фуекцию часть строки без создания новой. основная потеря времени при парсинге не преобразование строк в числа, а выделение памяти под новые строки, в том числе временные, которые по факту ненужн
zub
долгожитель
 
Сообщения: 2884
Зарегистрирован: 14.11.2005 23:51:26

Re: StrToInt на чистом паскале.

Сообщение Seenkao » 01.02.2022 00:16:21

zub писал(а):Строки нужны разные, а не какаято одна.

Когда я работаю с каким-то определённым видом строк, я только с ним и работаю. По сути, я считаю неправильным прыгать с одного вида на другой.
Но честно, пока даже вникать не хочу как мне это всё преобразовывать без потерь. А лепить тонны однообразных функций... ну бред (по моему).

С остальным посмотрю. Они работают одинаково, разница только в скорости (ну ещё в два раза быстрее работать будут :roll: ).

Добавлено спустя 36 минут 5 секунд:
zub писал(а):Основным должен быть вариант с (const PartStr:array of widechar/char)

Тогда в каком варианте должна идти выборка строки из строки для производных функций?
stencilStrToInt(const Str: String; begSten, endSten: integer); - в таком? (подобном).
Или чтоб функция сама искала число в строке?
Я извиняюсь, но вторым вариантом я даже заниматься не буду.
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

Re: StrToInt на чистом паскале.

Сообщение zub » 01.02.2022 01:24:42

>>stencilStrToInt(const Str: String; begSten, endSten: integer);
это можешь забыть, (const PartStr:array of ) его заменяет
zub
долгожитель
 
Сообщения: 2884
Зарегистрирован: 14.11.2005 23:51:26

Re: StrToInt на чистом паскале.

Сообщение Seenkao » 02.02.2022 12:36:10

Seenkao писал(а):ну ещё в два раза быстрее работать будут

не будут в два раза быстрее... это оказывается очередные проверки FPC на длину строки... но немного быстрее будет.

У меня матов нет!!! Мало того, что проверяется каждый "пук" на то, что строка другого типа или нет, так они ещё проверяют ограниченную строку с обычной.
Вам не пофиг какая приходящая строка? Если вы можете принимать строку любой длины. Зачем, ЗАЧЕМ идёт это долбанное сравнение одинаковых по типу строк на длину????

У меня объявлена строка как String[20], функция принимает строку String. Из-за этого идёт какая-то дополнительная проверка и автоматически скорость работы снижается.

zub, я про пользователей, а не про программистов. Им неудобно будет пользоваться подобной функцией (хотя можно забить просто).
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

Re: StrToInt на чистом паскале.

Сообщение zub » 02.02.2022 12:44:32

>>У меня объявлена строка как String[20], функция принимает строку String
Это совершенно разные типы строк, естественно они конвертируются.

Добавлено спустя 35 секунд:
даже если длинные строки выключены, строки всеравно разные
zub
долгожитель
 
Сообщения: 2884
Зарегистрирован: 14.11.2005 23:51:26

Re: StrToInt на чистом паскале.

Сообщение Seenkao » 02.02.2022 13:10:19

zub, ты мне головную боль подсунул. )))

zub писал(а):Это совершенно разные типы строк, естественно они конвертируются.

лично для меня это не явно. Я привык на низком уровне рассматривать всё...
Я бы просто даже длины строк сравнил и забыл, если б входящая строка была меньше длиной.

Добавлено спустя 1 минуту 51 секунду:
хотя возможно это и происходит. в цикле каждый раз... ))) как обычно туплю...
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

Re: StrToInt на чистом паскале.

Сообщение zub » 02.02.2022 14:04:14

сделай с (const PartStr:array of ) остальное все обертки над ними
zub
долгожитель
 
Сообщения: 2884
Зарегистрирован: 14.11.2005 23:51:26

Re: StrToInt на чистом паскале.

Сообщение Seenkao » 02.02.2022 14:13:06

не в этом проблема. А с одинарным символом и двойным. Char и WideChar. Лепить однообразные процедуры из-за того что символ широкий ни сколько не хочется. А значит надо делать подмену размеров символов. И больше проблема в том, как это предоставить, ведь не я же один буду этим пользоваться. Мне то вообще пофиг будет. )))
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

Re: StrToInt на чистом паскале.

Сообщение zub » 02.02.2022 14:18:35

generic
zub
долгожитель
 
Сообщения: 2884
Зарегистрирован: 14.11.2005 23:51:26

Пред.След.

Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 12

Рейтинг@Mail.ru
cron