Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.05.08;
Скачать: CL | DM;

Вниз

Преобразование Byte в Word?   Найти похожие ветки 

 
ZV ©   (2011-01-26 17:04) [0]

Как в Delphi  преобразовать 2 значения Byte в Word. На Си делаю побитовый сдвиг и наложение маски а как это сделать в Delphi? Может есть какая функция или делать так же как и на Си. Может кто покажет пример?


 
sniknik ©   (2011-01-26 17:19) [1]

> Может кто покажет пример?
w:= b;


 
Германн ©   (2011-01-26 17:21) [2]

1. Word1:=Byte1+(Byte2 shl 8)
2. type
 TMyWord = packed record
   case Integer of
     0 : (Byte1, Byte2 : Byte);
     1 : (Word1 : Word);
   end;


 
12 ©   (2011-01-26 17:33) [3]

var
 w:Word;
 b1, b2:Byte;
begin
 b1 := 0;
 b2 := 1;
 asm
   push ax
   mov al, b1
   mov ah, b2
   mov w, ax
   pop ax
 end;
 ShowMessage( IntToStr(w) );


 
sniknik ©   (2011-01-26 17:55) [4]

и еще на конкурс извращенцев...
procedure TForm1.Button1Click(Sender: TObject);
var
 w: Word;
 b: byte absolute w;
begin
 w:= 0;
 b:= $FF;
 ShowMessage(IntToStr(w));
end;


 
Игорь Шевченко ©   (2011-01-26 18:17) [5]


> Может есть какая функция или делать так же как и на Си.


а как на С сделано ?


 
Германн ©   (2011-01-26 18:20) [6]


> sniknik ©   (26.01.11 17:55) [4]
>
> и еще на конкурс извращенцев...

Не проходит по условию. Нужно два байта. :)


 
ZV ©   (2011-01-26 19:11) [7]


> а как на С сделано ?


unsigned int word;
unsigned char Ah, Bl;
Word=Ah;
word=(word<<8)|Bl;


То же на Delphi -  Word1:=Byte1+(Byte2 shl 8) (1 вариант от Германн)
нормально работает


 
DiamondShark ©   (2011-01-26 19:26) [8]

мне бы ваши проблемы


 
sniknik ©   (2011-01-26 19:28) [9]

> Не проходит по условию. Нужно два байта. :)
блин, упустил почему то, и получается фигню нес...
тогда так
var
 w: Word;
 b: array[0..1] of byte absolute w;
begin
 b[0]:= 1;
 b[1]:= 1;
 ShowMessage(IntToStr(w));
end;


 
DiamondShark ©   (2011-01-26 19:36) [10]

const
Q: array[byte,byte] of word = (
(0,1,2,3 ... 255),
(256, 257 ... 511)
...
(65280, ... ,65535)
);

w := Q[b1, b2];


 
sniknik ©   (2011-01-26 19:48) [11]

ну или тот же код что в [9] по мотивам asm ([3])
var
 w: Word;
begin
 asm
   mov byte ptr w[0], $01
   mov byte ptr W[1], $01
 end;
 ShowMessage(IntToStr(w));
end;


 
Студент   (2011-01-27 04:42) [12]

Занятно...))

А поясните пожалуйста "case Integer of" в record (кстати packed ни разу не пригодился, остаётся тож самое)?

А какой будет самым быстрым? Случайно не [10]?


 
KilkennyCat ©   (2011-01-27 04:55) [13]

strtoint(inttostr(b1) +inttostr(b2))


 
Студент   (2011-01-27 05:39) [14]

Ну... Вот с "Hex" такое бы сработало...


 
Inovet ©   (2011-01-27 05:45) [15]

> [12] Студент   (27.01.11 04:42)
> А какой будет самым быстрым?

Самый быстрый, который ничего не делает - с рекордом и с массивом, а [10] - это явный кандидат в победители на конкурсе извращенцев.:)))


 
Студент   (2011-01-27 06:50) [16]

Скомпилировал [10]... Неправильно считает... Нужно как-то по другому заполнять масив...
Про [11] говорит мол "Invalid combination of opcode and operands" если пытаться пременную подставить...((
У [13] результат неверный... Нужно через Hex: Word1:=HexToInt(IntToHex(Byte2, 2)+IntToHex(Byte1, 2));


 
Студент   (2011-01-27 06:51) [17]

Чуть не забыл:

procedure TForm1.Button8Click(Sender: TObject);
var i: Integer; S: String;
begin
S:="((0, ";
For i:=1 To 65534 Do
     Begin
     If (i mod 256)=0 Then
           S:=S+"),"#13#10"("+IntToStr(i)+", "
     Else
           If ((i+1) mod 256)=0 Then
                 S:=S+IntToStr(i)
           Else
                 S:=S+IntToStr(i)+", ";
     If (i mod 100)=0 Then
           S:=S+#13#10;
     End;
S:=S+"65535));";
Memo1.Text:=S;
end;


Да, я дурак..... %))


 
han_malign   (2011-01-27 08:41) [18]


> А какой будет самым быстрым? Случайно не [10]?

- случайно:
Германн ©   (26.01.11 17:21) [2]
1. Word1:=Byte1+(Byte2 shl 8)

- т.к. нет лишних обращений к памяти, а таких регистровых операций - современные CPU хавают по десятку за такт...
Недаром девиз Мелкомягких - "Все что можно пересчитать - лучше не хранить"...


 
RWolf ©   (2011-01-27 09:25) [19]


> Inovet ©   (27.01.11 05:45) [15]
> > [12] Студент   (27.01.11 04:42)> А какой будет самым быстрым?
> Самый быстрый, который ничего не делает - с рекордом и с
> массивом,

Самый быстрый — это сдвиг + OR.


 
Игорь Шевченко ©   (2011-01-27 10:30) [20]


> - т.к. нет лишних обращений к памяти, а таких регистровых
> операций - современные CPU хавают по десятку за такт...


обычно подобные утверждения подкрепляются тестовыми измерениями.


> Недаром девиз Мелкомягких - "Все что можно пересчитать -
>  лучше не хранить"...


кто не работает - не ест, ты спутал, батя


 
Германн ©   (2011-01-27 15:10) [21]


> han_malign   (27.01.11 08:41) [18]
>
>
> > А какой будет самым быстрым? Случайно не [10]?
>
> - случайно:
> Германн ©   (26.01.11 17:21) [2]
> 1. Word1:=Byte1+(Byte2 shl 8)
>
> - т.к. нет лишних обращений к памяти, а таких регистровых
> операций - современные CPU хавают по десятку за такт...
>

Хорошо подумал прежде чем написать такую чушь?
Нахрена нужны какие-то "операции" для того, чтобы всего лишь расположить два байта рядом в памяти???


 
han_malign   (2011-01-27 17:40) [22]


> ты спутал, батя

- я изредка брежу, но редко путаю:program hilo_word;
{$APPTYPE CONSOLE}
{$IF CompilerVersion >= 15.0}
{$WARN UNSAFE_TYPE OFF}
{$WARN UNSAFE_CODE OFF}
{$WARN UNSAFE_CAST OFF}
{$IFEND}
uses
 Windows, SysUtils;

const repeatCount = 10;

type
  TLoHiWord = packed record
  case Integer of
    0 : (Lo, Hi : Byte);
    1 : (value : Word);
  end;

  PByteArray = ^TByteArray;
  TByteArray = array[word]of byte;
  PWordArray = ^TWordArray;
  TWordArray = array[word]of TLoHiWord;

var _ft_start: TFileTime;
procedure _startProfile;
var _ftDumb: TFileTime;
begin
  GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_start);

end;
procedure _stopProfile(const title: string);
var _ft_end, _ftDumb: TFileTime;
begin
  GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_end);
  WriteLn(title:10,": ", _ft_end.dwHighDateTime - _ft_start.dwHighDateTime, ".", _ft_end.dwLowDateTime - _ft_start.dwLowDateTime:10, " x 100ns" );
end;

var rgwLookup: array[byte,byte]of word;
var
   pbl, pbh: PByteArray;
   pw: PWordArray;
   alloc, base, i, cnt: cardinal;
   si: TSystemInfo;
begin
  alloc:= 0;
  if( ParamCount > 0 )then alloc:= StrToIntDef(ParamStr(1), 0);
  if( alloc = 0 )then alloc:= 1024*1024*1024;

  GetSystemInfo(si);
  inc(alloc, cardinal(-alloc) mod si.dwAllocationGranularity);

  pbl:= PByteArray(VirtualAlloc(nil, alloc, MEM_COMMIT, PAGE_READWRITE));
  if( pbl = nil )then begin
     Writeln("Alloc failed - ", GetLastError());
  end;
  //prepare lookup table
  for i:= 0 to $FFFF do PWordArray(@rgwLookup)[i].value:= i;

  base:= alloc div 4;
  Write("GO"#13);
  _startProfile;
  for cnt:= 1 to repeatCount do begin
     for i:= 0 to base - 1 do PWordArray(pbl)[i].value:= Random(65536);
     Write(cnt:2,#13);
  end;
  _stopProfile("Random");

  pbh:= PByteArray(@pbl[base]);
  pw:= PWordArray(@pbh[base]);

  _startProfile;
  for cnt:= 1 to repeatCount do begin
     for i:= 0 to base - 1 do pw[i].value:= (pbh[i] shl 8) or pbl[i];
     Write(cnt:2,#13);
  end;
  _stopProfile("Combine");

  _startProfile;
  for cnt:= 1 to repeatCount do begin
     for i:= 0 to base - 1 do with pw[i] do begin
        lo:= pbl[i];
        hi:= pbh[i];
     end;
     Write(cnt:2,#13);
  end;
  _stopProfile("Direct");

  _startProfile;
  for cnt:= 1 to repeatCount do begin
     for i:= 0 to base - 1 do pw[i].value:= rgwLookup[pbl[i], pbh[i]];
     Write(cnt:2,#13);
  end;
  _stopProfile("Lookup");

  _startProfile;
  for cnt:= 1 to repeatCount do begin
     move(pbl^, pw^, base*2);
     Write(cnt:2,#13);
  end;
  _stopProfile("just copy");

  VirtualFree(pbl, 0, MEM_RELEASE);
end.

-----------------------------------------------------
   Random: 0. 106406250 x 100ns
  Combine: 0.  52500000 x 100ns
   Direct: 0.  55781250 x 100ns
   Lookup: 0.  91406250 x 100ns
just copy: 0.  33125000 x 100ns


 
Игорь Шевченко ©   (2011-01-27 18:12) [23]

Я несколько изменил порядок тестов

  Combine: 0.  13437500 x 100ns
just copy: 0.   7031250 x 100ns
   Lookup: 0.  15156250 x 100ns
   Random: 0.  25625000 x 100ns
   Direct: 0.  13281250 x 100ns


 
Игорь Шевченко ©   (2011-01-27 18:13) [24]

program BtoWProfile;
{$APPTYPE CONSOLE}
{$IF CompilerVersion >= 15.0}
{$WARN UNSAFE_TYPE OFF}
{$WARN UNSAFE_CODE OFF}
{$WARN UNSAFE_CAST OFF}
{$IFEND}
uses
 Windows,
 SysUtils;

const repeatCount = 10;

type
 TLoHiWord = packed record
 case Integer of
   0 : (Lo, Hi : Byte);
   1 : (value : Word);
 end;

 PByteArray = ^TByteArray;
 TByteArray = array[word]of byte;
 PWordArray = ^TWordArray;
 TWordArray = array[word]of TLoHiWord;

var _ft_start: TFileTime;
procedure _startProfile;
var _ftDumb: TFileTime;
begin
 GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_start);

end;
procedure _stopProfile(const title: string);
var _ft_end, _ftDumb: TFileTime;
begin
 GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_end);
 WriteLn(title:10,": ", _ft_end.dwHighDateTime - _ft_start.dwHighDateTime, ".", _ft_end.dwLowDateTime - _ft_start.dwLowDateTime:10, " x 100ns" );
end;

var rgwLookup: array[byte,byte]of word;
var
  pbl, pbh: PByteArray;
  pw: PWordArray;
  alloc, base, i, cnt: cardinal;
  si: TSystemInfo;
begin
 alloc:= 0;
 if( ParamCount > 0 )then alloc:= StrToIntDef(ParamStr(1), 0);
 if( alloc = 0 )then alloc:= 256*1024*1024;

 GetSystemInfo(si);
 inc(alloc, cardinal(-alloc) mod si.dwAllocationGranularity);

 pbl:= PByteArray(VirtualAlloc(nil, alloc, MEM_COMMIT, PAGE_READWRITE));
 if( pbl = nil )then begin
    Writeln("Alloc failed - ", GetLastError());
 end;
 //prepare lookup table
 for i:= 0 to $FFFF do PWordArray(@rgwLookup)[i].value:= i;

 base:= alloc div 4;
 Write("GO"#13);
 
 pbh:= PByteArray(@pbl[base]);
 pw:= PWordArray(@pbh[base]);

 _startProfile;
 for cnt:= 1 to repeatCount do begin
    for i:= 0 to base - 1 do pw[i].value:= (pbh[i] shl 8) or pbl[i];
    Write(cnt:2,#13);
 end;
 _stopProfile("Combine");

 _startProfile;
 for cnt:= 1 to repeatCount do begin
    move(pbl^, pw^, base*2);
    Write(cnt:2,#13);
 end;
 _stopProfile("just copy");

 _startProfile;
 for cnt:= 1 to repeatCount do begin
    for i:= 0 to base - 1 do pw[i].value:= rgwLookup[pbl[i], pbh[i]];
    Write(cnt:2,#13);
 end;
 _stopProfile("Lookup");

 _startProfile;
 for cnt:= 1 to repeatCount do begin
    for i:= 0 to base - 1 do PWordArray(pbl)[i].value:= Random(65536);
    Write(cnt:2,#13);
 end;
 _stopProfile("Random");

 _startProfile;
 for cnt:= 1 to repeatCount do begin
    for i:= 0 to base - 1 do with pw[i] do begin
       lo:= pbl[i];
       hi:= pbh[i];
    end;
    Write(cnt:2,#13);
 end;
 _stopProfile("Direct");

 VirtualFree(pbl, 0, MEM_RELEASE);
end.


 
han_malign   (2011-01-27 18:27) [25]


>    Lookup: 0.  15156250 x 100ns
>    Random: 0.  25625000 x 100ns

- молодец, но даже учитывая, что тест всегда обращается к rgwLookup[0, 0], поскольку память инициализирована нулями - таблица все равно самый плохой вариант...


 
han_malign   (2011-01-27 18:33) [26]

и естественно - все Page Fault достались Combine...


 
Игорь Шевченко ©   (2011-01-27 18:39) [27]


> и естественно - все Page Fault достались Combine...


отсюда возникает вопрос - что тестируем ?


 
Inovet ©   (2011-01-27 19:54) [28]

> [18] han_malign   (27.01.11 08:41)

> [19] RWolf ©   (27.01.11 09:25)
> Самый быстрый — это сдвиг + OR.

Это в произвольном случае, а когда надо всё время и так и так обращаться, то лучше ничего не делать а сразу организовать хранение рядом, я об этом говорил. Хотя как оно там будет на каком железе должно

> [20] Игорь Шевченко ©   (27.01.11 10:30)
> подкрепляются тестовыми измерениями


 
han_malign   (2011-01-28 09:02) [29]


> отсюда возникает вопрос - что тестируем ?

- вы ничего не тестируете, поскольку подбираете условия по каким то выгодным вам критериям...

Между прочим, если совсем исключить из теста Combine инициализацию страниц памяти нулем при первом обращении(заполнив Random-ом всю выделенную память, а не первую половину) - отрыв еще больше увеличивается...

З.Ы. Самое прикольное это - rgwLookup[Hi, Lo] - как по вашему вычисляется смещение, если адресная арифметика поддерживает только масштабы 1, 2, 4, 8...


 
12 ©   (2011-01-28 09:44) [30]


> han_malign   (27.01.11 17:40) [22]


> Игорь Шевченко ©   (27.01.11 18:13) [24]

вы - маньяки :)


 
han_malign   (2011-01-28 09:45) [31]

И о главном: почему опасно пользоваться приведением типа для доступа к битовым полям(в Delphi, в C - все порадужней), и когда таблица таки выгодна...
(посвящается структуре TRGBQuad)
program hilo_word;
{$APPTYPE CONSOLE}
{$IF CompilerVersion >= 15.0}
{$WARN UNSAFE_TYPE OFF}
{$WARN UNSAFE_CODE OFF}
{$WARN UNSAFE_CAST OFF}
{$IFEND}
uses
 Windows, SysUtils;

const repeatCount = 10;

type
  TLoHiWord = packed record
  case Integer of
    0 : (Lo, Hi : Byte);
    1 : (value : Word);
  end;
  PLoHiWord = ^TLoHiWord;

  PByteArray = ^TByteArray;
  TByteArray = array[word]of byte;
  PWordArray = ^TWordArray;
  TWordArray = array[word]of word;

var _ft_start: TFileTime;
procedure _startProfile;
var _ftDumb: TFileTime;
begin
  GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_start);

end;
procedure _stopProfile(const title: string);
var _ft_end, _ftDumb: TFileTime;
begin
  GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_end);
  WriteLn(title:10,": ", _ft_end.dwHighDateTime - _ft_start.dwHighDateTime, ".", _ft_end.dwLowDateTime - _ft_start.dwLowDateTime:10, " x 100ns" );
end;

function TRANSFORM(val: word): word;
begin
  //ну пускай будет BGR16 в BGR15
  Result:= val and $1F or (val shr 1) and $7FE;
end;

const _title: array[0..2]of string = ("Combine", "Cast", "Map");

var rgwLookup: array[byte,byte]of word;
var
   pbl, pbh: PByteArray;
   pw: PWordArray;
   alloc, base, i, cnt: cardinal;
   si: TSystemInfo;
   _b2w: TLoHiWord;
   choice: integer;
   _hitChoice: array[0..2]of integer;
   fdwDoneChoice: LongWord;
begin
  alloc:= 0;
  if( ParamCount > 0 )then alloc:= StrToIntDef(ParamStr(1), 0);
  if( alloc = 0 )then alloc:= 1024*1024*1024;

  GetSystemInfo(si);
  inc(alloc, cardinal(-alloc) mod si.dwAllocationGranularity);

  pbl:= PByteArray(VirtualAlloc(nil, alloc, MEM_COMMIT, PAGE_READWRITE));
  if( pbl = nil )then begin
     Writeln("Alloc failed - ", GetLastError());
  end;
  //prepare lookup table
  for i:= 0 to $FFFF do PWordArray(@rgwLookup)[i]:= TRANSFORM(i);

  base:= alloc div 4;
  Write("GO"#13);
  _startProfile;
  for i:= 0 to base*2 - 1 do PWordArray(pbl)[i]:= Random(65536);
  _stopProfile("Random");

  pbh:= PByteArray(@pbl[base]);
  pw:= PWordArray(@pbh[base]);

  FillChar(_hitChoice, sizeof(_hitChoice), 0);
  fdwDoneChoice:= 0;

  while( fdwDoneChoice <> 7 )do begin
     //дабы никому не пришло в голову упрекнуть меня в предвзятости
     choice:= Random(3);
     inc(_hitChoice[choice]);
     if( _hitChoice[choice] > 2 )then fdwDoneChoice:= fdwDoneChoice or (1 shl choice);
     _startProfile;
     for cnt:= 1 to repeatCount do begin
        case(choice)of
        0: for i:= 0 to base - 1 do pw[i]:= TRANSFORM((pbh[i] shl 8) or pbl[i]);
        1: for i:= 0 to base - 1 do with _b2w do begin
           lo:= pbl[i];
           hi:= pbh[i];
           pw[i]:= TRANSFORM(value);
        end;
        2: for i:= 0 to base - 1 do pw[i]:= rgwLookup[pbl[i], pbh[i]];
        end;
        Write(cnt:2,#13);
     end;
     _stopProfile(_title[choice]);
  end;

  VirtualFree(pbl, 0, MEM_RELEASE);
end.

--------------------------------------
     Cast: 0. 274687500 x 100ns
      Map: 0.  90000000 x 100ns
  Combine: 0. 141250000 x 100ns
  Combine: 0. 141250000 x 100ns
     Cast: 0. 275000000 x 100ns
     Cast: 0. 275000000 x 100ns
      Map: 0.  89843750 x 100ns
  Combine: 0. 141250000 x 100ns
      Map: 0.  90000000 x 100ns


 
RWolf ©   (2011-01-28 10:20) [32]

C:\>hilo_word.exe 67108864
   Random: 0.   2187500 x 100ns
  Combine: 0.  10781250 x 100ns
  Combine: 0.  10625000 x 100ns
  Combine: 0.  10468750 x 100ns
     Cast: 0.  19218750 x 100ns
  Combine: 0.  10468750 x 100ns
      Map: 0.  18593750 x 100ns
  Combine: 0.  10468750 x 100ns
     Cast: 0.  20156250 x 100ns
      Map: 0.  18593750 x 100ns
      Map: 0.  18437500 x 100ns
     Cast: 0.  19687500 x 100ns


Атлон64 3000+. Налицо двукратный выигрыш shl-or.
И почему вдруг в Дельфи опасно пользоваться приведением типа, и чем Дельфи в этом смысле отличается от Си?


 
RWolf ©   (2011-01-28 10:28) [33]

или смысл в том, чтобы загнать тест в свопы?


 
uniken1 ©   (2011-01-31 08:04) [34]


> и еще на конкурс извращенцев...

Интересно на какое место попадет функция
TwoByteToWord из Indy модуль(IdGlobal)? Собственный динамический массив с изменением размера и с двойным преобразованием.
Появляются подозрения, что Indy не очень-то оптимальна по производительности.


 
Anatoly Podgoretsky ©   (2011-01-31 08:48) [35]

> uniken1  (31.01.2011 08:04:34)  [34]

Лучше подумать, что курили разработчки и почему с нами не поделились


 
sniknik ©   (2011-01-31 09:28) [36]

> uniken1 ©   (31.01.11 08:04) [34]
если бы не динамический массив... не все так страшно, хотя предпочел бы типа (соглашения о передаче параметров из функции вроде неизменны) -

function TwoByteToWord(AByte1, AByte2: Byte): Word;
asm
  mov al, AByte1
  mov ah, AByte2
end;


> почему с нами не поделились
главный вопрос...


 
Anatoly Podgoretsky ©   (2011-01-31 11:22) [37]

> sniknik  (31.01.2011 09:28:36)  [36]

Правильно, главный, их код нам и нафиг не нужен.



Страницы: 1 вся ветка

Текущий архив: 2011.05.08;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.015 c
15-1295731785
Юрий
2011-01-23 00:29
2011.05.08
С днем рождения ! 23 января 2011 воскресенье


2-1296050681
ZV
2011-01-26 17:04
2011.05.08
Преобразование Byte в Word?


3-1258272518
Drowsy
2009-11-15 11:08
2011.05.08
Хранимые процедуры. InterBase6.


15-1296111273
Jeer
2011-01-27 09:54
2011.05.08
Проблема парсинга TSQLQuery (dbExpress)..


11-1234297339
alex649
2009-02-10 23:22
2011.05.08
исчезает текст обработчика событий в Д7 при кпопытке компиляции