Конвертация Int64 с разделителем групп разрядов: неужели?!)

Вопросы программирования на Free Pascal, использования компилятора и утилит.

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

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение iskander » 08.02.2023 22:28:27

avmaksimov писал(а):А почему вы используете массивы, а не используете код символа?

Да я бы со всем моим удовольствием, а какой код будет у символа '42'?
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение avmaksimov » 08.02.2023 23:15:07

RRYTY писал(а):Почему не засунуть в Format extended, а не int64?

Ну, наверное, потому что, что никакой разницы: просто явная конвертация. Я проверял. Результат тот же.

Добавлено спустя 7 минут 28 секунд:
iskander писал(а):
avmaksimov писал(а):А почему вы используете массивы, а не используете код символа?

Да я бы со всем моим удовольствием, а какой код будет у символа '42'?

В смысле? Вы же по одному символу разбираете. Код символа 4 и код символа 2 знаете же?)

В generi.inc нашёл исходник. Там делается, как я и имел в виду. Код получается так: "char(l-(m1*10)+byte('0'));".
avmaksimov
новенький
 
Сообщения: 21
Зарегистрирован: 17.10.2010 12:38:54

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение iskander » 08.02.2023 23:30:51

avmaksimov писал(а):В смысле? Вы же по одному символу разбираете.

Код: Выделить всё
...
type
  TChar2 = array[0..1] of Char;
...

Вот как это сможет быть одним символом?
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение avmaksimov » 09.02.2023 00:15:09

iskander писал(а):
avmaksimov писал(а):В смысле? Вы же по одному символу разбираете.

Код: Выделить всё
...
type
  TChar2 = array[0..1] of Char;
...

Вот как это сможет быть одним символом?

Не заметил, что речь про тест. Кстати, не нравился мне ваш case)), но по факту лучше ничего не придумали тут тоже: https://forum.lazarus.freepascal.org/index.php?topic=39880.0 . Действительно, быстрее. Через логарифм медленно.

Вы не пробовали коммитить на GitLab решение в RTL? Кстати, и IntToStrF можно было бы на базе этого, добавив пару параметров для солидности (использовать разделитель или нет, а также число символов, чтобы нули спереди, если что).

Если ваше решение, возможно, немного адаптировав, добавлю в https://github.com/doublecmd, вы не против?
avmaksimov
новенький
 
Сообщения: 21
Зарегистрирован: 17.10.2010 12:38:54

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение iskander » 09.02.2023 00:21:07

avmaksimov писал(а):Вы не пробовали коммитить на GitLab решение в RTL?

Да упаси меня господь.
avmaksimov писал(а):Если ваше решение, возможно, немного адаптировав, добавлю в https://github.com/doublecmd, вы не против?

Нет проблем.
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение avmaksimov » 09.02.2023 00:25:25

iskander писал(а):
avmaksimov писал(а):Вы не пробовали коммитить на GitLab решение в RTL?

Да упаси меня господь.

А если я?) Не тщеславия ради, но популярности Паскала для))
avmaksimov
новенький
 
Сообщения: 21
Зарегистрирован: 17.10.2010 12:38:54

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение Seenkao » 09.02.2023 03:38:58

Код: Выделить всё
// свободная лицензия ZLib. Просьба прикладывать к коду.
function IntToStrNew(Value: Int64): string;
var
  _Res: array[0..25] of Char = (' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
  __res: PChar;
  i, j: QWord;
  ii: Byte;
  minus: boolean = false;
begin
  if Value = 0 then
  begin
    Result := '0';
    exit;
  end;
  __res := @_Res[25];
  {$push}
  {$Q-}{$R-}
  j := 1;
  if Value < 0 then
    minus := true;
  i := abs(Value);
  while i > 999 do
  begin
    ii := i mod 10;
    i := i div 10;
    __res^ := char(ii + 48);
    dec(__res);

    ii := i mod 10;
    i := i div 10;
    __res^ := char(ii + 48);
    dec(__res);

    ii := i mod 10;
    i := i div 10;
    __res^ := char(ii + 48);
    dec(__res, 2);
    inc(j, 4);
  end;
  while i > 9 do
  begin
    ii := i mod 10;
    i := i div 10;
    __res^ := char(ii + 48);
    dec(__res);
    inc(j);
  end;
  __res^ := char(i + 48);
  if minus then
  begin
    inc(j);
    dec(__res);
    __res^ := '-';
  end;

  SetLength(Result, j);
  move(_Res[26 - j], Result[1], j);
  {$pop}
end;

результат на 5 000 000 итераций (мой нижний), кодировка страницы UTF-8:
IntToStrTSv1: 1229
3 806 104 050 474 772 600

IntToStrTSv2: 646
3 806 104 050 474 772 600

IntToStrTSvMove: 1272
3 806 104 050 474 772 600

IntToStrNew: 508
3 806 104 050 474 772 600

Код свободный, мне не может принадлежать, так как часть кода взята у участников сообщества. За что им благодарность!

Данный код работает с Int64, как с положительными, так и с отрицательными числами.
Учтены проблемы с переводом чисел, при любой (надеюсь) кодировке страницы. Возможны проблемы при каких-то кодировках, но вроде все влияния на кодировку убрал. И, вероятно, код можно ещё ускорить. )))

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

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение iskander » 09.02.2023 08:11:30

avmaksimov писал(а):А если я?) Не тщеславия ради, но популярности Паскала для))

Опять же, никаких проблем.
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение RRYTY » 09.02.2023 11:03:57

avmaksimov писал(а):...
Суть проблемы в том, что максимальное значение Int64 - 9 223 372 036 854 775 807, а при любом преобразовании в число с плавающей точкой цифра 7 пропадает и остаётся только: 9 223 372 036 854 775 800 ...


Не могу воспроизвести косяк - семерка не потерялась.

Код: Выделить всё
procedure TMF.Button1Click(Sender: TObject);
var
  b_i: Int64;
  b_e: extended;
begin
  If TryStrToInt64 (MF.Edit1.Text, b_i) then
    begin
      b_e:= b_i;
      MF.Label1.Caption:= Format ('%n', [b_e]);
    end;
end;
У вас нет необходимых прав для просмотра вложений в этом сообщении.
RRYTY
постоялец
 
Сообщения: 187
Зарегистрирован: 25.12.2021 10:00:32

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение avmaksimov » 09.02.2023 11:14:16

RRYTY писал(а):
avmaksimov писал(а):...
Суть проблемы в том, что максимальное значение Int64 - 9 223 372 036 854 775 807, а при любом преобразовании в число с плавающей точкой цифра 7 пропадает и остаётся только: 9 223 372 036 854 775 800 ...


Не могу воспроизвести косяк - семерка не потерялась.

Код: Выделить всё
procedure TMF.Button1Click(Sender: TObject);
var
  b_i: Int64;
  b_e: extended;
begin
  If TryStrToInt64 (MF.Edit1.Text, b_i) then
    begin
      b_e:= b_i;
      MF.Label1.Caption:= Format ('%n', [b_e]);
    end;
end;

Это Винда? Похоже на Гном) Я писал, что проблема только в Windows (10).
avmaksimov
новенький
 
Сообщения: 21
Зарегистрирован: 17.10.2010 12:38:54

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение RRYTY » 09.02.2023 11:18:06

avmaksimov писал(а):Это Винда? Похоже на Гном) Я писал, что проблема только в Windows (10).


Опс. Сейчас проверю в виндах.
Абсолютно точно. Надо будет поосторожнее с виндами. :(

Все же надо явно указывать на операционную систему. Три дня на вас большими глазами смотрю, понять ничего не могу.
Последний раз редактировалось RRYTY 09.02.2023 13:14:12, всего редактировалось 1 раз.
RRYTY
постоялец
 
Сообщения: 187
Зарегистрирован: 25.12.2021 10:00:32

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение Alex2013 » 09.02.2023 11:49:59

Ну если "оптимизировать почти до последнего бита" тогда можно написать например так:
Код: Выделить всё
function IntToStrTSvMove(const AValue: SizeUInt): shortstring;
var
  i,j,  vSrcLen,  vSCount, vResLen:Byte;
  STmp: shortstring;
begin
  Str(AValue, STmp);
  vSrcLen := Length(STmp);
  vSCount := ((vSrcLen - 1) div 3);
  vResLen := vSrcLen + vSCount;
  Result[0]:=Chr(vResLen);
  for I := 1 to vSCount do begin
      J:=i shl 2;
      Move(STmp[vSrcLen - (j-i) + 1], Result[vResLen - j + 2], 3); // ???
      Result[vResLen - j+1] := FormatSettings.ThousandSeparator;
  end;
  Move(STmp[1], Result[1], vSrcLen - vSCount*3);
end;

(Опять старый ноутбук )
Win32
IntToStrTSv1: 5984
3 944 166 137

IntToStrTSv2: 1547
3 944 166 137

IntToStrTSvMove: 1562
3 944 166 137

Win64 (Q1)
IntToStrTSv1: 4282
3 849 148 015 466 334 344

IntToStrTSv2: 2391
3 849 148 015 466 334 344

IntToStrTSvMove: 2531
3 849 148 015 466 334 344

Win64 (Q4)
IntToStrTSv1: 3422
5 457 206 742 568 232 034

IntToStrTSv2: 2281
5 457 206 742 568 232 034

IntToStrTSvMove: 2328
5 457 206 742 568 232 034

Почти догнал лидера ! :wink: ( Разумеется это просто прикол из серии "мне за державу обидно!" ) :mrgreen:
(Для комлекта можно и в линуксе перекомпилировать (он на этой "тачанке" есть) но лениво )
Последний раз редактировалось Alex2013 09.02.2023 12:31:32, всего редактировалось 1 раз.
Alex2013
долгожитель
 
Сообщения: 2923
Зарегистрирован: 03.04.2013 11:59:44

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение Seenkao » 09.02.2023 12:23:47

Alex2013 писал(а):Почти догнал лидера !

какого лидера? ))) там вроде как уже был обгон лидера. ))) С полной заменой функции "str".
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение Alex2013 » 09.02.2023 12:34:43

Seenkao писал(а):какого лидера? ))) там вроде как уже был обгон лидера. ))) С полной заменой функции "str".

Значит я его проспал! :oops: Если сразу заменить "str", тогда разумеется можно сделать еще быстрее.
Зы
Кстати в IntToStrTSv2 тоже можно shortstring использовать. ( Вообщем совершенству нет предела! :wink: )
Последний раз редактировалось Alex2013 09.02.2023 12:53:16, всего редактировалось 1 раз.
Alex2013
долгожитель
 
Сообщения: 2923
Зарегистрирован: 03.04.2013 11:59:44

Re: Конвертация Int64 с разделителем групп разрядов: неужели

Сообщение Seenkao » 09.02.2023 12:51:10

Alex2013, на самом деле функцию "str" сложнее заменить, чем "val". Я думал что на паскале чистом даже невозможно. Но видимо ошибался.

Добавлено спустя 4 минуты 30 секунд:
Re: Конвертация Int64 с разделителем групп разрядов: неужели?!)
для перевода строки в число с плавающей запятой и обратно, надо будет вникать как устроено это самое "число с плавающей запятой"?
Я имею в виду для полноценной замены, а не использовать готовые решения.
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

Пред.След.

Вернуться в Free Pascal Compiler

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

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

Рейтинг@Mail.ru