![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
HexToStr
kiwooo © (2006-08-15 13:16:00)Привет! Искал в инетрнете способы перевода Hex - значения в Str элемент. Т.е. например
Hex := '757475';
HStr := HexToStr(Hex);
Итог HStr = "utu"
Решение проблемы-то я нашел, но интересует, как быстрее и лучше сделать эту операцию (HexToStr).
Шпиён (2006-08-16 05:57:00) [1]
> А прирост скорости какой большой! Сдуреть просто...
По производительности (компилятор D6, про другие ничего не могу сказать) варианты
1) Len:=Lenght(s) div 2;
2) Len:=integer(pointer(integer(pointer(s))-4)^) shr 1;
должны быть примерно одинаковы:
1) Len:=Lenght(s) div 2;
mov eax,[ebp-$04]
call@StrLen
sar eax,1
@StrLen:
test eax,eax
jz +$03
mov eax,[eax-$04]
ret
2) Len:=integer(pointer(integer(pointer(s))-4)^) shr 1;
mov eax,[ebp-$04]
sub eax,$04
jno +$05
call @IntOver
mov eax,[eax]
shr eax,1
ps
И оба будут быстрее, чем [7]
function StrLen(const Str: PChar): Cardinal; assembler;
asm
MOV EDX,EDI
MOV EDI,EAX
MOV ECX,0FFFFFFFFH
XOR AL,AL
REPNE SCASB
MOV EAX,0FFFFFFFEH
SUB EAX,ECX
MOV EDI,EDX
end;
Шпиён (2006-08-16 05:24:00) [2]
> Fay © (16.08.06 04:24) [41]
> 2 Шпиён (16.08.06 1:40) [37]
> Это называется "очень сильное колдунство"
> Что, по-твоему выдаст HexToStr('') ?
"Что-то вроде такого" не означает "сделай точно так же без всяких проверок входных данных" -)
HexToStr('') в таком варианте выдаст AV.
Если ты заметил, в [36] написано
Попробовал бы воспользоваться Lenght (более универсальный
способ)или получить длину строки примерно как integer(pointer(integer(pointer(s))- 4)^)
И, возможно, использовал бы сдвиг вправо вместо деления
нацело -)
Основная мысль была - заменить StrLen.
[37] просто иллюстрация к [36].
Fay (2006-08-16 04:32:00) [3]А прирост скорости какой большой! Сдуреть просто...
function HexToStr(const s : string) : string;
var
Len : integer;
begin
Len := integer(pointer(integer(pointer(s)) - 4)^) shr 1;
SetLength(Result, Len);
SetLength(Result, HexToBin(pchar(s), pchar(result), Len));
end;
function HexToStr2(const s : string) : string;
var
Len : integer;
begin
Len := Length(s) div 2;
SetLength(Result, Len);
SetLength(Result, HexToBin(pchar(s), pchar(result), Len));
end;
procedure TForm1.Button1Click(Sender : TObject);
var
i : Integer;
tc : DWORD;
s : string;
begin
s := '30313233343536373839';
tc := GetTickCount;
for i := 0 to 999999 do
s := Copy(s + HexToStr(s), 1, 20);
ShowMessage(Format('%d', [GetTickCOunt - tc]));
end;
Fay (2006-08-16 04:24:00) [4]2 Шпиён (16.08.06 1:40) [37]
Это называется "очень сильное колдунство"
Что, по-твоему выдастHexToStr('')?
Пусик (2006-08-16 03:24:00) [5]
> KilkennyCat © (16.08.06 03:07) [38]
По крайней мере, код Шпиёна из [37] весьма быстр.
Пусик (2006-08-16 03:22:00) [6]
> KilkennyCat © (16.08.06 03:07) [38]
> Есть способ еще проще.
Подавай его сюда.
Если проще и быстрее, то совсем хорошо-)
KilkennyCat (2006-08-16 03:07:00) [7]Есть способ еще проще.
Шпиён (2006-08-16 01:40:00) [8]Что-то вроде такого:
function HexToStr(const s:string):string;
var Len:integer;
begin
Len:=integer(pointer(integer(pointer(s))-4)^) shr 1;
SetLength(Result,Len);
SetLength(Result,HexToBin(pchar(s), pchar(result), Len));
end;
Шпиён (2006-08-16 01:22:00) [9]И еще передал бы в HexToStr не PChar, а const строку, и вообще не "вычислял" бы длину буфера такимспособом -)
Попробовал бы воспользоваться Lenght (более универсальный способ) или получить длину строки примерно как integer(pointer(integer(pointer(s))-4)^)
И, возможно, использовал бы сдвиг вправо вместо деления нацело -)
Шпиён (2006-08-16 01:11:00) [10]
> Хотя вот сейчас думаю, как можно еще оптимизировать
Ну, для начала я бы не вычислял StrLen(s)div 2 дважды. -)
Пусик (2006-08-16 01:08:00) [11]
> Германн © (16.08.06 01:06) [33]
> > Пусик © (16.08.06 00:52) [31]> > > > Германн © (16.
> 08.06 00:24) [29]> > > Код хоть и неоптимальный, но вполне
> имеет право на жизнь.> Наглядный и простой.> Там, где нет
> особых требований к скорости выполнения кода,> вполне подойдет.
> Ну так приведи "оптимальный" код. Никто не будет возражать.
>
Так в [7] код достаточно оптимальный. Хотя вот сейчас думаю, как можно еще оптимизировать.
Германн (2006-08-16 01:06:00) [12]
> Пусик © (16.08.06 00:52) [31]
>
>
> > Германн © (16.08.06 00:24) [29]
>
>
> Код хоть и неоптимальный, но вполне имеет право на жизнь.
> Наглядный и простой.
> Там, где нет особых требований к скорости выполнения кода,
> вполне подойдет.
Ну так приведи "оптимальный" код. Никто не будет возражать.
>
> PS.
> Я не "злобная". Я белая и пушистая, пока меня не трогают.
>
Дык я и не считал тебя злобной! :-)
Это всё
> tesseract © (15.08.06 21:58) [21]
и
> Kolan © (15.08.06 23:37) [28]
Германн (2006-08-16 01:01:00) [13]
> Шпиён (16.08.06 00:43) [30]
>
>
> > Германн © (16.08.06 00:24) [29]
>
> хочешь?
> Ассемблерный вариант в D6 закомментирован -)
>
Да я то не хочу. Но раз уж ты назвался груздем, так и полезай туда. :-) Залез. Вижу.
Пусик (2006-08-16 00:52:00) [14]
> Германн © (16.08.06 00:24) [29]
Код хоть и неоптимальный, но вполне имеет право на жизнь. Наглядный и простой.
Там, где нет особых требований к скорости выполнения кода, вполне подойдет.
PS.
Я не "злобная". Я белая и пушистая, пока меня не трогают.
Шпиён (2006-08-16 00:43:00) [15]
> Германн © (16.08.06 00:24) [29]
хочешь?
Ассемблерный вариант в D6 закомментирован -)
Delphi5 (Classes.pas)
function HexToBin(Text, Buffer: PChar; BufSize: Integer): Integer; assembler;
asm
PUSH ESI
PUSH EDI
PUSH EBX
MOV ESI,EAX
MOV EDI,EDX
MOV EBX,EDX
MOV EDX,0
JMP @@1
@@0: DB 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
DB -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
DB -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
DB -1,10,11,12,13,14,15
@@1: LODSW
CMP AL,'0'
JB @@2
CMP AL,'f'
JA @@2
MOV DL,AL
MOV AL,@@0.Byte[EDX-'0']
CMP AL,-1
JE @@2
SHL AL,4
CMP AH,'0'
JB @@2
CMP AH,'f'
JA @@2
MOV DL,AH
MOV AH,@@0.Byte[EDX-'0']
CMP AH,-1
JE @@2
OR AL,AH
STOSB
DEC ECX
JNE @@1
@@2: MOV EAX,EDI
SUB EAX,EBX
POP EBX
POP EDI
POP ESI
end;
Германн (2006-08-16 00:24:00) [16]
> Хотя для достаточно длинной строки я бы использовал код
> HexToBin из более свежих версий Delphi.
Ну так уж если сказал assembler, так и приводи ассемблерный код. Иначе "злобн(ый)ая Пусик опять скажет о "неэффективности". :-)
Kolan (2006-08-15 23:37:00) [17]
> Пусик решилопять всех покозлить.
Это он? 8-/
Пусик (2006-08-15 23:12:00) [18]> tesseract © (15.08.06 22:40) [24]
> tesseract © (15.08.06 21:58) [21]
...Пусик решил опять всех покозлить...
перегруз у меня :-)
Тогда не надо проблемы с больной головы на здоровую перекладывать(т.е. на автора). Из топика всё ясно и понятно - что имел ввиду автор. Если кто-то не в состоянии понять вопроса, то автор в том не виноват.
> Kolan © (15.08.06 22:59) [25]
> > доказал преподователь по теории чисел в 1998 годуНу вообщем
> Hex - система счисления.
Из топика всё ясно и понятно - что имел ввиду автор. Если кто-то не в состоянии понять вопроса, то автор в том не виноват.
Шпиён (2006-08-15 23:04:00) [19]
> тогда присоединяюсь к [2].
По моему, из [0] четко видно, что должна делать функция HexToStr -)
Присоединяюсь к [3], [4] и [7]
[3] - если версия Delphi не позволяет. Хотя для достаточно длинной строки я бы использовал код HexToBin из более свежих версий Delphi.
Delphi 6:
function HexToBin(Text, Buffer: PChar; BufSize: Integer): Integer; assembler;
const
Convert: array['0'..'f'] of SmallInt =
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,10,11,12,13,14,15);
var
I: Integer;
begin
I := BufSize;
while I > 0 do
begin
if not (Text[0] in ['0'..'f']) or not (Text[1] in ['0'..'f']) then Break;
Buffer[0] := Char((Convert[Text[0]] shl 4) + Convert[Text[1]]);
Inc(Buffer);
Inc(Text, 2);
Dec(I);
end;
Result := BufSize - I;
end;
Kolan (2006-08-15 22:59:00) [20]
> доказал преподователь по теории чисел в 1998 году
Ну вообщем Hex - система счисления.
Я имел в виду что в Delphi нет формата для таких чисел(вродеDouble, Intger) а используетсяstring.. Мож я и не прав, но впрос что должна делатьHexToStrу меня вознит сразу...