Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

HexToStr


Страницы:   1 2 3

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у меня вознит сразу...


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо