Страница 3 из 4

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

СообщениеДобавлено: 20.01.2022 15:38:54
Seenkao
Изначально я просто для себя создавал более быстрый вариант 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...


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

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

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

СообщениеДобавлено: 21.01.2022 20:46:51
Alexander
Такое впечатление, что не работает на отрицательных числах.

Код: Выделить всё
>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.

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

СообщениеДобавлено: 23.01.2022 00:03:14
Seenkao
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 - обозначает восьмеричную систему (не я придумывал). Можно конечно сделать исключение, тогда ведущие нули будут автоматически из десятичного и из восьмеричного чисел убираться.

Возникает вопрос, что важнее: совместимость или возможность разделения по системам?

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

СообщениеДобавлено: 23.01.2022 22:21:27
Alexander
Спасибо ! Теперь работает как надо.

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

СообщениеДобавлено: 25.01.2022 07:27:53
Seenkao
Alexander, не за что.
Но вот подобные правки потом выявляют неточности в коде, которые так же приходится править. )))

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

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

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

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

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

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

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

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

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

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

СообщениеДобавлено: 01.02.2022 00:16:21
Seenkao
zub писал(а):Строки нужны разные, а не какаято одна.

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

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

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

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

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

СообщениеДобавлено: 01.02.2022 01:24:42
zub
>>stencilStrToInt(const Str: String; begSten, endSten: integer);
это можешь забыть, (const PartStr:array of ) его заменяет

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

СообщениеДобавлено: 02.02.2022 12:36:10
Seenkao
Seenkao писал(а):ну ещё в два раза быстрее работать будут

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

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

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

zub, я про пользователей, а не про программистов. Им неудобно будет пользоваться подобной функцией (хотя можно забить просто).

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

СообщениеДобавлено: 02.02.2022 12:44:32
zub
>>У меня объявлена строка как String[20], функция принимает строку String
Это совершенно разные типы строк, естественно они конвертируются.

Добавлено спустя 35 секунд:
даже если длинные строки выключены, строки всеравно разные

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

СообщениеДобавлено: 02.02.2022 13:10:19
Seenkao
zub, ты мне головную боль подсунул. )))

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

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

Добавлено спустя 1 минуту 51 секунду:
хотя возможно это и происходит. в цикле каждый раз... ))) как обычно туплю...

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

СообщениеДобавлено: 02.02.2022 14:04:14
zub
сделай с (const PartStr:array of ) остальное все обертки над ними

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

СообщениеДобавлено: 02.02.2022 14:13:06
Seenkao
не в этом проблема. А с одинарным символом и двойным. Char и WideChar. Лепить однообразные процедуры из-за того что символ широкий ни сколько не хочется. А значит надо делать подмену размеров символов. И больше проблема в том, как это предоставить, ведь не я же один буду этим пользоваться. Мне то вообще пофиг будет. )))

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

СообщениеДобавлено: 02.02.2022 14:18:35
zub
generic