![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как быстро узнать что в строке одни нули? [D7, XP]
RusSun © (2016-09-03 09:01:00)Сабж.
RusSun (2016-09-04 13:43:00) [1]to All Спасибо большущее.
Строки от коротких ~16 до более длинных 64 и более символов.
тема закрыта.
Sha (2016-09-04 12:57:00) [2]> Игорь Шевченко © (04.09.16 12:48) [18]
> Я проверял далеко на не последней, это проверялось на D2006.
ну значит там RTL уже поправлена
> Кстати, на юникодных '0' это не байт.
именно поэтому я так аккуратно и назвал свою функцию
Sha (2016-09-04 12:52:00) [3]> manaka © (04.09.16 12:44) [17]
Берем за образец что-нибудь вроде
function CharPos(ch: char; const s: string): integer;
var
i: integer;
begin;
for i:=1 to Length(s) do if s[i]=ch then begin;
Result:=i; exit;
end;
Result:=0;
end;
и делаем что-нибудь вроде
function NonBlankPos(const s: string): integer;
var
i: integer;
begin;
for i:=1 to Length(s) do if s[i]>#32 then begin; //или <>
Result:=i; exit;
end;
Result:=0;
end;
Игорь Шевченко (2016-09-04 12:48:00) [4]Sha © (04.09.16 12:29) [16]
> В последних версиях Delphi, вероятно, так и будет
Я проверял далеко на не последней, это проверялось на D2006. Кстати, на юникодных '0' это не байт.
manaka (2016-09-04 12:44:00) [5]Удалено модератором
Примечание: Флудить завязывай
Sha (2016-09-04 12:29:00) [6]> Игорь Шевченко © (04.09.16 12:09) [15]
В последних версиях Delphi, вероятно, так и будет
за счет инлайна и улучшенной функции сравнения.
А у меня (как и у автора) D7.
Там моя быстрее в 2 раза даже на длинных строках.
И мне не хочется думать, что это из-за не очень нового компа )
Игорь Шевченко (2016-09-04 12:09:00) [7]Sha © (04.09.16 11:36) [13]
Кстати, на длинных строках у меня быстрее получается. Но не думаю, что автору нужно длинные строки сравнивать
Text: "0000000000000000000000000000000000000000000000000000000", length: 55
Sha: 0,167 seconds to compare 10000000 times.
Sniknik: 0,698 seconds to compare 10000000 times.
Igor Schevchenko: 0,143 seconds to compare 10000000 times.
Игорь Шевченко (2016-09-04 12:05:00) [8]Дабы не утруждать мозг раздумиями:
Text: "000000000000", length: 12
Sha: 0,090 seconds to compare 10000000 times.
Sniknik: 0,635 seconds to compare 10000000 times.
Igor Schevchenko: 0,110 seconds to compare 10000000 times.
Text: "0", length: 1
Sha: 0,095 seconds to compare 10000000 times.
Sniknik: 0,561 seconds to compare 10000000 times.
Igor Schevchenko: 0,096 seconds to compare 10000000 times.
Text: "Edit1", length: 5
Sha: 0,090 seconds to compare 10000000 times.
Sniknik: 0,563 seconds to compare 10000000 times.
Igor Schevchenko: 0,090 seconds to compare 10000000 times.
Sha (2016-09-04 11:36:00) [9]Вариант с развернутым циклом:
function IsBufferOfByte(pBuf: pointer; Len: integer; Value: byte): boolean;
const
Test: array[0..3] of cardinal= (0, $FF, $FFFF, $FFFFFF);
var
Mask: cardinal;
pEnd: pointer;
label
ExitFalse;
begin;
if Len=0 then goto ExitFalse;
Mask:=Value * $01010101;
pEnd:=@pIntegerArray(pBuf)[Len shr 3 * 2];
while pBuf<>pEnd do begin;
if Int64Rec(pBuf^).Lo<>Mask then goto ExitFalse;
if Int64Rec(pBuf^).Hi<>Mask then goto ExitFalse;
inc(pInt64(pBuf));
end;
if Len and 4<>0 then begin;
if Cardinal(pBuf^)<>Mask then goto ExitFalse;
inc(pCardinal(pBuf));
end;
Len:=Len and 3;
if (Len=0) or ((pCardinal(pBuf)^ xor Mask) and Test[Len]=0) then begin;
Result:=true;
exit;
end;
ExitFalse:
Result:=false;
end;
Sha (2016-09-04 09:19:00) [10]> sniknik © (04.09.16 01:52) [11]
> и кстати думаю довольно быстро будет.
Думаю, в разы разница будет.
А если в [9] цикл развернуть, то и на порядок.
sniknik (2016-09-04 01:52:00) [11]а ну да, в оригиналном вопросе просто проверка на все нули, с неопределенной/заданной длиной, еще проще -
function TestStringsForZeros(const Source: string): Boolean;
begin
Result:= Source = StringOfChar('0', Length(Source));
end;
и кстати думаю довольно быстро будет.
sniknik (2016-09-04 01:48:00) [12]быстро, красиво, ... надо проще делать.
function TestStringsForZeros(const Source: string; Count: integer): Boolean;
begin
Result:= Source = StringOfChar('0', Count);
end;
Sha (2016-09-03 22:55:00) [13]Так тоже должно быть довольно быстро, хотя и не очень красиво, наверное:
function IsBufferOfByte(pBuf: pointer; Len: integer; Value: byte): boolean;
var
Mask: cardinal;
label
ExitFalse;
begin;
if Len=0 then goto ExitFalse;
Mask:=Value * $01010101;
while Len>=4 do begin;
if pCardinal(pBuf)^<>Mask then goto ExitFalse;
inc(pCardinal(pBuf));
dec(Len,4);
end;
if (Len=0) or ((pCardinal(pBuf)^ xor Mask) shl ((4-Len) shl 3)=0) then begin;
Result:=true;
exit;
end;
ExitFalse:
Result:=false;
end;
Использовать так:
var
s: string;
begin;
s:='aaaaa';
Result:=IsBufferOfByte(pointer(s),Length(s),byte('a')))));
end;
Игорь Шевченко (2016-09-03 18:50:00) [14]RusSun © (03.09.16 11:26) [5]
Примерно так:
const
Zeros: PChar = '00000000000000000000000000000000000000000000000000'; //Сколько надо по длине
function TestStringsForZeros (const Source: string): Boolean; inline;
begin
Result := CompareMem(PChar(Source), Zeros, Length(Source));
end;
Leonid Troyanovsky (2016-09-03 14:53:00) [15]
> RusSun © (03.09.16 11:26) [5]
function IsStringMonoChar(const s: String; c: Char): Boolean;
var
i, k, L: Longint;
p: PChar;
t: array [0..3] of Char;
begin
L := Length(s);
Result := L > 0;
if not Result then
Exit;
p := PChar(s);
FillChar(t, 4, c);
k := L div 4;
for i := 0 to k-1 do
begin
Result := PLongint(p)^ = PLongint(@t)^;
if not Result then
Exit;
inc(p, 4);
end;
k := L mod 4;
for i := L-k+1 to L do
begin
Result := s[i] = c;
if not Result then
Exit;
end;
end;
no tested.
--
Regards, LVT.
RusSun (2016-09-03 12:00:00) [16]
> быстрой функцией сравнения.
можно по точнее
RusSun (2016-09-03 11:26:00) [17]to Игорь Шевченко
> finally end; //of finally
> Ты зачем так пишешь ? Не надо.
потому Не часто пользуюсь, try http://www.delphibasics.ru/Try.php,
что не означает, что так как я написал верно и так всем надо делать. =)
to Leonid Troyanovsky,Игорь Шевченко.
1ое можно код.
2ое строка имеет переменную длину.
С уважением, RusSun.
Игорь Шевченко (2016-09-03 10:52:00) [18]
> finally end; //of finally
Ты зачем так пишешь ? Не надо.
Если надо быстро, заведи длинный образец и сравнивай с ним быстрой функцией сравнения.
Leonid Troyanovsky (2016-09-03 09:53:00) [19]
> RusSun © (03.09.16 09:17) [2]
> к символу. И в конце result:=true/false
Не в конце, а до первого несовпадения.
Ну, и сравнивать можно сразу по 4 (or 8) байт.
--
Regards, LVT.
RusSun (2016-09-03 09:17:00) [20]"Пришло" пока только два "варианта".
1 сравнивать от символа к символу. И в конце result:=true/false
второй вариант что-то вроде
2try
result:=false;
if StrToInt(s) = 0 then
result:=true
finally end; //of finally
Есть ли ещё?