powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Быстрая замена символа
25 сообщений из 259, страница 4 из 11
Быстрая замена символа
    #39676680
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpub
Пардон, не разобрал на телефоне.
А, при чём здесь длина строки вообще? она и так в -4 байта лежит...


Серьёзно? Я тут говорю, что в 4 байтах можно по маске сразу понять, есть ли символ. А он не понимает. Эх ты.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676684
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Kazantsev Alexeyzinpub,

Вот с проверкой четвёрками:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
function _Replace(const s : AnsiString) : AnsiString;
var

 l    : Integer;
 i    : Integer;
 cpos : PAnsiChar;

begin

 Result := Copy(s, 1);

 l    := Length(Result);
 cpos := Pointer(Result);

 for i := 1 to l div 4 do
  begin

   if cpos[0] = ',' then
    cpos[0] := '.';

   if cpos[1] = ',' then
    cpos[1] := '.';

   if cpos[2] = ',' then
    cpos[2] := '.';

   if cpos[3] = ',' then
    cpos[3] := '.';

   inc(cpos, 4);

  end;

 for i := 1 to l mod 4 do
  begin

   if cpos[0] = ',' then
    cpos[0] := '.';

   inc(cpos);

  end;

end;


Работает на 30% быстрее PEnd. Правда не знаю, умеет ли Delphi 5 div и mod оптимизировать.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676685
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ГирлионайльдоzinpubПардон, не разобрал на телефоне.
А, при чём здесь длина строки вообще? она и так в -4 байта лежит...


Серьёзно? Я тут говорю, что в 4 байтах можно по маске сразу понять, есть ли символ. А он не понимает. Эх ты.

Так это всё равно на 4 маски сравнивать...
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676688
afgm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpubЭээ и что за камень? поставил у себя 50 000...
i5 6500
Ты сам постил аналогичные результаты для 50 000 21586838
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676689
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
zinpubГирлионайльдопропущено...



Серьёзно? Я тут говорю, что в 4 байтах можно по маске сразу понять, есть ли символ. А он не понимает. Эх ты.

Так это всё равно на 4 маски сравнивать...

Хотя нет, кажется понял... Ща буду думать...
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676694
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
afgmzinpubЭээ и что за камень? поставил у себя 50 000...
i5 6500
Ты сам постил аналогичные результаты для 50 000 21586838

Это не я ...
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676696
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpub,

Там в коде нескольких функций (ReplaceCharByPChar в частности) допущена ошибка о которой я уже писал - меняются символы в исходной строке (копирования данных не происходит - выше скорость):
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
function ReplaceCharByPChar(const s: string): string;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: PChar;
  i: Integer;
begin
  Result := s;
  P := Pointer(Result);
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676708
afgm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpubЭто не я ...
Я ошибся, но там порядок похожий.
1. В коде CNT_RUN с циклом не связана.
2. Погрешности now нет. Переделал на StopWatch. Всё аналогично.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676720
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpub,

Вот тут можно подробнее узнать о этом
http://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676727
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Kazantsev Alexeyzinpub,

Там в коде нескольких функций (ReplaceCharByPChar в частности) допущена ошибка о которой я уже писал - меняются символы в исходной строке (копирования данных не происходит - выше скорость):
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
function ReplaceCharByPChar(const s: string): string;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: PChar;
  i: Integer;
begin
  Result := s;
  P := Pointer(Result);



Да, косякнул...
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676731
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
afgmzinpubЭто не я ...
Я ошибся, но там порядок похожий.
1. В коде CNT_RUN с циклом не связана.
2. Погрешности now нет. Переделал на StopWatch. Всё аналогично.

CNT_RUN с Edit'ом связана...

Код покажи...
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676738
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я делал PosByte на этих бинарных трюках, выходило шустрее даже асмового Pos для анси строк. Но вот незадача - для юникод строк это уже не работает.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676739
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpubДа, косякнул...
Другие функции проверь.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676746
afgm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpubКод покажи...
source
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Diagnostics;

type

  ApChar = AnsiChar;
  ApString = AnsiString;
  ApPChar = PAnsiChar;

  TCommatFunc = function(s: ApString): ApString;

  TForm1 = class(TForm)
    btnCommaToPoint: TButton;
    mmo1: TMemo;
    mmo2: TMemo;
    btnFill: TButton;
    btnTest: TButton;
    procedure btnCommaToPointClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btnFillClick(Sender: TObject);
    procedure btnTestClick(Sender: TObject);
  private
    { Private declarations }
     function RunFunc(Func: TCommatFunc): Int64;

    procedure FillRandomText(const iFactor, iCharCount: Integer);
  public
    { Public declarations }
  end;

const
  CNT_RUN = 50000;

var
  Form1: TForm1;

implementation

{$R *.dfm}


function ForkReplaceC_lodsw(s: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
begin
  Result := s;

  asm
    Push  ESI
    Push  EBX

    Mov   EAX,Result
    Or    EAX,EAX
    Jz    @Exit
    Mov   ESI,[EAX]
    Or    ESI,ESI
    Jz    @Exit

    Mov   BH,COMMA_
    Mov   BL,DOT_
    Cmp   AH,BL
    Jz    @Exit

    Mov   ECX,[ESI-4]
    Jecxz @Exit
    push ECX

    shr ECX,1

    Cld
  @Next:
    Lodsw
    Cmp   AH,BH
    Jne   @Skip1
    Mov   [ESI-1],BL
  @Skip1:
    Cmp   AL,BH
    Jne   @Skip
    Mov   [ESI-2],BL
  @Skip:
    Dec   ECX
    Jnz   @Next

    // ------------------------
    pop ECX
    and ECX,2
    jz @Exit
  @Next20:
    Lodsb
    Cmp   AH,BH
    Jne   @Skip20
    Mov   [ESI-1],BL
  @Skip20:
    Dec   ECX
    Jnz   @Next20
  @Exit:
    Pop  EBX
    Pop  ESI

  end;
end;


function ForkReplaceC_lodsw_FIX(s: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
begin
  Result := s;

  asm
    Push  ESI
    Push  EBX

    Mov   EAX,Result
    Or    EAX,EAX
    Jz    @Exit
    Mov   ESI,[EAX]
    Or    ESI,ESI
    Jz    @Exit

    Mov   BH,COMMA_
    Mov   BL,DOT_
    Cmp   AH,BL
    Jz    @Exit

    Mov   ECX,[ESI-4]
    Jecxz @Exit
    push ECX

    shr ECX,1

    Cld
  @Next:
    Lodsw
    Cmp   AH,BH
    Jne   @Skip1
    Mov   [ESI-1],BL
  @Skip1:
    Cmp   AL,BH
    Jne   @Skip
    Mov   [ESI-2],BL
  @Skip:
    Dec   ECX
    Jnz   @Next

    // ------------------------
    pop ECX
    and ECX,2
    jz @Exit
  @Next20:
    Lodsb
    Cmp   AH,BH
    Jne   @Skip20
    Mov   [ESI-1],BL
  @Skip20:
    Dec   ECX
    Jnz   @Next20
  @Exit:
    Pop  EBX
    Pop  ESI

  end;
end;

function PEnd(const s: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: ApPChar;
  PEnd: Pointer;
begin
  Result := s;
  P := Pointer(Result);
  PEnd := P + Length(s);
  while P < PEnd do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    Inc(P);
  end;
end;


function PEnd_ASM(const s: ApString): ApString;
asm
// Unit1.pas.175: begin
                          push ebp
                          mov ebp,esp
                          push ebx
                          push esi
                          mov esi,edx
                          mov ebx,eax
//Unit1.pas.176: Result := s;
                          mov eax,esi
                          mov edx,ebx
                          call System.@LStrAsg
//Unit1.pas.177: P := Pointer(Result);
                          mov eax,[esi]
//Unit1.pas.178: PEnd := P + Length(s);
                          mov edx,ebx
                          test edx,edx
                          jz @005d2c0b
                          sub edx,$04
                          mov edx,[edx]
@005d2c0b:
                          add edx,eax

                          mov esi, $2e //--


//Unit1.pas.179: while P < PEnd do
                          cmp edx,eax
                          jbe @005d2c1e
//Unit1.pas.181: if P^ = COMMA_ then
@005d2c11:
{
                          cmp byte ptr [eax],$2c
                          jnz @005d2c19
//Unit1.pas.182: P^ := DOT_;
                          mov byte ptr [eax],$2e
}
//--
//                         cmp byte ptr [eax],$2c
//                           cmove  eax,ebx
//                         cmove
                          xor ebx,ebx
                          mov bl, byte ptr [eax]
                          xor ecx, $2e
                          //xor ebx, $000000FF
                          cmp bl, $2c
                          cmovne ecx, ebx        // if char<>',' then ecx <- char
////                          mov bl, $2e
////                          cmove ecx, ebx
                          cmove cx, si         //  if char=',' then ecx <- '.'


////                          mov ecx, ebx
                          mov byte ptr [eax], cl
//--
//Unit1.pas.183: Inc(P);
@005d2c19:
                         inc eax
//Unit1.pas.179: while P < PEnd do
                          cmp edx,eax
                          jnbe @005d2c11
//Unit1.pas.185: end;
@005d2c1e:
                          pop esi
                          pop ebx
                          pop ebp
                          ret
end;


function ReplaceCharByPChar(const s: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: ApPChar;
  i: Integer;
begin
  Result := s;
  P := Pointer(Result);
  for i := 0 to Length(s) - 1 do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    Inc(P);
  end;
end;

function TestMy(const s: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: ApPChar;
begin
  Result := s;
  P := Pointer(Result);
  while P^ <> #0 do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    Inc(P);
  end;
end;


type
  TaRecode = array [ApChar] of ApChar;

var
  fRecode: TaRecode;

procedure Init();
var
  c: ApChar;
begin
  for c := Low(ApChar) to High(ApChar) do
    fRecode[c] := c;
  fRecode[','] := '.';
end;

function Recode(str: ApString): ApString;
var
  i: Integer;
begin
  Result := str;
  for i := 1 to Length(Result) do
    Result[i] := fRecode[Result[i]];
end;

var
  MinTest: int64;
  IdxMin, IdxCurr: Integer;

procedure TForm1.btnCommaToPointClick(Sender: TObject);
 function FormatOutput(const aFuncName: ApString; const iRunTime: Int64)
    : ApString;
  begin
    Result := Format('%-20s -> %d', [aFuncName, iRunTime]);
  end;

begin
  MinTest := 100000000000000000;
  IdxMin := 0;
  IdxCurr := 0;

  mmo1.Lines.Add('------------------------------------------------------');



  mmo1.Lines.Add(FormatOutput('ForkReplaceC_lodsw',
    RunFunc(@ForkReplaceC_lodsw)));

  mmo1.Lines.Add(FormatOutput('ForkReplaceC_lodsw',
    RunFunc(@ForkReplaceC_lodsw)));

  mmo1.Lines.Add(FormatOutput('ForkReplaceC_lodsw_FIX',
    RunFunc(@ForkReplaceC_lodsw_FIX)));

  mmo1.Lines.Add(FormatOutput('ForkReplaceC_lodsw_FIX',
    RunFunc(@ForkReplaceC_lodsw_FIX)));


  mmo1.Lines.Add(FormatOutput('ReplaceCharByPChar',
    RunFunc(@ReplaceCharByPChar)));

  mmo1.Lines.Add(FormatOutput('TestMy', RunFunc(@TestMy)));

  mmo1.Lines.Add(FormatOutput('PEnd', RunFunc(@PEnd)));
  mmo1.Lines.Add(FormatOutput('PEnd_ASM', RunFunc(@PEnd_ASM)));
  mmo1.Lines.Add(FormatOutput('Recode', RunFunc(@Recode)));

  mmo1.Lines.Add(FormatOutput('Самый быстрый: ' + IntToStr(IdxMin + 1),
    MinTest));

end;

procedure TForm1.FillRandomText(const iFactor, iCharCount: Integer);
var
  i: Integer;
  s: ApString;
begin
  s := '';

  for i := 0 to iCharCount do
  begin
    if Random(10) > iFactor then
      s := s + ','
    else
      s := s + Chr(40 + Trunc(Random(150)));
  end;

  mmo2.Text := s;

end;

function TForm1.RunFunc(Func: TCommatFunc): Int64;
var
  aStartTime: TDateTime;
  i: Integer;
  s: ApString;
  sw: TStopwatch;
begin
  s := mmo2.Text;

//  aStartTime := Now;
  sw := TStopwatch.StartNew;
  for i := 0 to CNT_RUN - 1 do
    Func(s);

//  Result := Now - aStartTime;
  sw.Stop;
  Result := sw.ElapsedMilliseconds;

  if MinTest - Result > 0 then
  begin
    MinTest := Result;
    IdxMin := IdxCurr;
  end;
  Inc(IdxCurr);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Init();
end;

procedure TForm1.btnFillClick(Sender: TObject);
begin
 FillRandomText(20, 10000);
end;

procedure TForm1.btnTestClick(Sender: TObject);
begin
  ShowMessage(PEnd('123,asd'));
  ShowMessage(PEnd_ASM('123,asd'));
end;

end.




Можешь выслать свою тестовую программу целиком на afgm[гав]mail.ru ?
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676807
afgm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
afgmМожешь выслать свою тестовую программу...
Ответ по поводу скорости уже нашёл
Код: pascal
1.
2.
  FillRandomText(StrToInt(edtFactor.Text), 250);
  FillRandomText(20, 10000);
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676830
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. Многопоточность никак не поможет?
Мне с файлами, бывает, сильно помогает.
2. MMX никак не поможет?
Ну и с объемными данными тоже.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676833
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я нашёл способ, как проверить, есть ли какой нибудь символ в 4 байтном слове

Код: pascal
1.
p := 'T,xt';




Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
Символ: T Есть!
Символ: x Есть!
Символ: , Есть!

Символ: e Нету!

Символ: t Есть!

Символ: 3 Нету!
Символ: K Нету!
Символ: j Нету!
Символ: o Нету!
Символ: # Нету!
Символ: Ф Нету!
Символ: Я Нету!
Символ: С Нету!
Символ: . Нету!
Символ: X Нету!





Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
program Project4;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

function checkChar(Sum: NativeUInt; Ch: byte): Boolean;
begin
  Sum := Sum xor (72340172838076673 * Ch);
  Result := ((Sum - $01010101) and not Sum and $80808080) <> 0;
end;


var
  p: PansiChar;


procedure assert(c: char);
var
  s: string;
begin
  if checkChar(PNativeUInt(p)^, ord(c)) then
    s := ' Есть!'
  else
    s := ' Нету!';

  Writeln('Символ: ', c, s);
end;

begin
  p := 'T,xt';
  assert('T');
  assert('x');
  assert(',');
  assert('e');
  assert('t');
  assert('3');
  assert('K');
  assert('j');
  assert('o');
  assert('#');
  assert('Ф');
  assert('Я');
  assert('С');
  assert('.');
  assert('X');

  Readln;

end.

...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676860
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет.

zinpubМожет, кто подскажет, как ещё быстрее можно...

Начал с такого
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
function FastCommatopoint(s: string): string;
var
  i: Integer;
begin
  Result := s;
  for i := 1 to Length(s) do
    if Result[i] = ',' then
      Result[i] := '.';
end;



Можно читать по 4 байта. У меня получилось примерно в два раза вышеприведенного варианта:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
function UseLodsD( s : AnsiString ) : AnsiString;
begin
  Result := s;

  asm
       Push     ESI
       Push     EDI
       Push     EBX

       Mov      EAX,    Result

       Mov      ESI,    [EAX]
       Mov      ECX,    [ESI - 4]
       Mov      EBX,    ECX
       And      EBX,    011b
       Shr      ECX,    2

  @@10:
       LodsD
       Mov      EDX,    4

  @@20:
       Cmp      AL,     ','
       Jne      @@30
       Mov      EDI,    ESI
       Sub      EDI,    EDX
       Mov      Byte Ptr [EDI], '.'

  @@30:
       Shr      EAX,    8
       Dec      EDX
       Test     EDX,    EDX
       Jnz      @@20

       Loop     @@10

       Test     EBX,    EBX
       Jz       @@90

       Mov      ECX,    EBX

  @@40:
       LodsB
       Cmp      AL,     ','
       Jne      @@50
       Mov      Byte Ptr [ESI - 1], '.'

  @@50:
       Loop    @@40

  @@90:
       Pop      EBX
       Pop      EDI
       Pop      ESI
  end;
end;



С уважением, Poleosv.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676872
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я сделать самую быструю функцию! Кто сможет меня вздёрнуть?) (Только не надо SSE, он точно быстрее будет)

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
------------------------------------------------------
ReplaceCharByPChar   -> 00:02:879
TestMy               -> 00:02:368
PEnd                 -> 00:02:797
Rep4Bytes            -> 00:01:084
Самый быстрый: 4     -> 00:01:084
------------------------------------------------------
ReplaceCharByPChar   -> 00:02:945
TestMy               -> 00:02:470
PEnd                 -> 00:02:975
Rep4Bytes            -> 00:01:097
Самый быстрый: 4     -> 00:01:097



Код тестовый
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  ApChar = AnsiChar;
  ApString = AnsiString;
  ApPChar = PAnsiChar;

  TCommatFunc = function(s: ApString): ApString;

  TForm1 = class(TForm)
    btnCommaToPoint: TButton;
    mmo1: TMemo;
    mmo2: TMemo;
    btnFill: TButton;
    Memo1: TMemo;
    procedure btnCommaToPointClick(Sender: TObject);
    procedure btnFillClick(Sender: TObject);
  private
    function RunFunc(Func: TCommatFunc): TDateTime;

    procedure FillRandomText(const iFactor, iCharCount: Integer);
    { Private declarations }
  public
    { Public declarations }
  end;

const
  CNT_RUN = 100000; // РАБОТАЕТ

var
  Form1: TForm1;

implementation

{$R *.DFM}

function ReplaceCharByPChar(s: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: ApPChar;
  i: Integer;
begin
  Result := s;
  P := Pointer(Result);
  for i := 0 to Length(s) - 1 do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    Inc(P);
  end;
end;

function TestMy(s: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: ApPChar;
begin
  Result := s;
  P := Pointer(Result);
  while P^ <> #0 do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    Inc(P);
  end;
end;

function PEnd(s: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: ApPChar;
  PEnd: Pointer;
begin
  Result := s;
  P := Pointer(Result);
  PEnd := P + Length(s);
  while P < PEnd do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    Inc(P);
  end;
end;

function Rep4Bytes(str: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P, C: ApPChar;
  len: Cardinal;
  Sum: NativeUInt;
  Offset: byte;
  i: Integer;
begin
  Result := str;
  P := Pointer(Result);
  len := Length(str);

  while len >= sizeof(ApPChar) do
  begin
    Sum := PNativeUInt(P)^ xor (72340172838076673 * ord(COMMA_));
    if ((Sum - $01010101) and not Sum and $80808080) <> 0 then
    begin
      for Offset := 0 to 3 do
      begin
        C := ApPChar(P + Offset);
        if C^ = COMMA_ then
          C^ := DOT_;
      end;
    end;
    dec(len, sizeof(ApPChar));
    Inc(P, sizeof(ApPChar));
  end;

  while len <> 0 do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    dec(len);
    Inc(P);
  end;
end;

var
  MinTest: TDateTime;
  IdxMin, IdxCurr: Integer;

procedure TForm1.btnCommaToPointClick(Sender: TObject);

  function FormatOutput(const aFuncName: ApString; const iRunTime: TDateTime)
    : ApString;
  begin
    Result := Format('%-20s -> %s', [aFuncName, FormatDateTime('NN:SS:ZZZ',
      iRunTime)]);
  end;

begin
  MinTest := TDateTime(1000000000);
  IdxMin := 0;
  IdxCurr := 0;

  mmo1.Lines.Add('------------------------------------------------------');

  mmo1.Lines.Add(FormatOutput('ReplaceCharByPChar',
    RunFunc(@ReplaceCharByPChar)));

  mmo1.Lines.Add(FormatOutput('TestMy', RunFunc(@TestMy)));

  mmo1.Lines.Add(FormatOutput('PEnd', RunFunc(@PEnd)));
  mmo1.Lines.Add(FormatOutput('Rep4Bytes', RunFunc(@Rep4Bytes)));

  mmo1.Lines.Add(FormatOutput('Самый быстрый: ' + (IdxMin + 1).ToString,
    MinTest));

end;

function TForm1.RunFunc(Func: TCommatFunc): TDateTime;
var
  aStartTime: TDateTime;
  i: Integer;
  s: ApString;
begin
  s := mmo2.Text;

  aStartTime := Now;

  for i := 0 to CNT_RUN - 1 do
    Func(s);

  Result := Now - aStartTime;

  if MinTest - Result > 0 then
  begin
    MinTest := Result;
    IdxMin := IdxCurr;
  end;
  Inc(IdxCurr);
end;

procedure TForm1.FillRandomText(const iFactor, iCharCount: Integer);
var
  i: Integer;
  s: ApString;
begin
  s := '';

  for i := 0 to iCharCount do
  begin
    s := s + ','
  end;

  mmo2.Text := s;

end;

procedure TForm1.btnFillClick(Sender: TObject);
begin
  FillRandomText(20, 10000);
end;

end.




Функция

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
function Rep4Bytes(str: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P, C: ApPChar;
  len: Cardinal;
  Sum: NativeUInt;
  Offset: byte;
  i: Integer;
begin
  Result := str;
  P := Pointer(Result);
  len := Length(str);

  while len >= sizeof(ApPChar) do
  begin
    Sum := PNativeUInt(P)^ xor (72340172838076673 * ord(COMMA_));
    if ((Sum - $01010101) and not Sum and $80808080) <> 0 then
    begin
      for Offset := 0 to 3 do
      begin
        C := ApPChar(P + Offset);
        if C^ = COMMA_ then
          C^ := DOT_;
      end;
    end;
    dec(len, sizeof(ApPChar));
    Inc(P, sizeof(ApPChar));
  end;

  while len <> 0 do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    dec(len);
    Inc(P);
  end;
end;
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676875
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov,

Твоя asm функция капелька в море в производительности
Rep4Bytes -> 00:01:083
UseLodsD -> 00:02:088
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
------------------------------------------------------
ReplaceCharByPChar   -> 00:02:873
TestMy               -> 00:02:401
PEnd                 -> 00:02:810
Rep4Bytes            -> 00:01:083
UseLodsD             -> 00:02:088
Самый быстрый: 4     -> 00:01:083
------------------------------------------------------
ReplaceCharByPChar   -> 00:02:876
TestMy               -> 00:02:370
PEnd                 -> 00:02:814
Rep4Bytes            -> 00:01:080
UseLodsD             -> 00:02:070
Самый быстрый: 4     -> 00:01:080

...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676878
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для тех кто может подумать что моя функция не работает Раз она быстрая очень


(Включить оптимизацию в настройке проекта. И вставить этот код в консольное приложение)

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
program Project4;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

type
  ApChar = AnsiChar;
  ApString = AnsiString;
  ApPChar = PAnsiChar;

function Rep4Bytes(str: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P, C: ApPChar;
  len: Cardinal;
  Sum: NativeUInt;
  Offset: byte;
  i: Integer;
begin
  Result := str;
  P := Pointer(Result);
  len := Length(str);

  while len >= sizeof(ApPChar) do
  begin
    Sum := PNativeUInt(P)^ xor (72340172838076673 * ord(COMMA_));
    if ((Sum - $01010101) and not Sum and $80808080) <> 0 then
    begin
      for Offset := 0 to 3 do
      begin
        C := ApPChar(P + Offset);
        if C^ = COMMA_ then
          C^ := DOT_;
      end;
    end;
    dec(len, sizeof(ApPChar));
    Inc(P, sizeof(ApPChar));
  end;

  while len <> 0 do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    dec(len);
    Inc(P);
  end;
end;

var
  P: string;

begin
  P := ',,,,,,,,,,,,,,,,,SIVJRG J jrigjre шокпшкп ,,,,,,,,,,с';
  Writeln(Rep4Bytes(P));

  Readln;

end.

...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676879
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpubKazantsev Alexeyzinpub,

Там в коде нескольких функций (ReplaceCharByPChar в частности) допущена ошибка о которой я уже писал - меняются символы в исходной строке (копирования данных не происходит - выше скорость):
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
function ReplaceCharByPChar(const s: string): string;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: PChar;
  i: Integer;
begin
  Result := s;
  P := Pointer(Result);



Да, косякнул...


вставь между этими операторами
Код: pascal
1.
UniqueString(Result);



и чтобы сразу видеть инвалидные функции в тело RunFunc можно добавить предварительную проверку
Код: pascal
1.
2.
3.
4.
5.
  t:=Func(s);
  if (pos(',',s)=0) or (pos(',',t)<>0) or (t=s) then begin;
   Result:=1;
   exit;
   end



и наконец, в объявление функций лучше добавить const
Код: pascal
1.
  TCommatFunc = function(const s: ApString): ApString;



также можно рассмотреть процедуры
Код: pascal
1.
  TCommaProc = procedure(var s: ApString);
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676898
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гирлионайльдо,

чей-то софт напоминает) но тоже инвалид.

Кстати, по-хорошему, можно было бы обобщить на любую пару символов и с масками игру с масками осилить до конца.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676899
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ГирлионайльдоЯ сделать самую быструю функцию! Кто сможет меня вздёрнуть?)
Это как раз тот момент, когда оптимизация превращает код в колдунство. И опять же, это только для однобайтовых строк.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676906
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
За то она самая быстрая, из всех предложенных вариантов :D И я этим горжусь,,даже на asm никто не осилил быстрее
...
Рейтинг: 0 / 0
25 сообщений из 259, страница 4 из 11
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Быстрая замена символа
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]