Byte to word delphi

 
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]

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


    msm.ru

    Нравится ресурс?

    Помоги проекту!

    Пожалуйста, выделяйте текст программы тегом [сode=pas] … [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.


    Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
    1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
    2. Как «свернуть» программу в трей.
    3. Как «скрыться» от Ctrl + Alt + Del (заблокировать их и т.п.)
    4. Как прочитать список файлов, поддиректорий в директории?
    5. Как запустить программу/файл?
    … (продолжение следует) …


    Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
    Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


    Внимание
    Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
    Повторная попытка — 60 дней. Последующие попытки бан.
    Мат в разделе — бан на три месяца…

    >
    byte+byte=word
    , преобразование 2-х переменных byte в word

    • Подписаться на тему
    • Сообщить другу
    • Скачать/распечатать тему

      


    Сообщ.
    #1

    ,
    04.04.06, 07:53

      Добрый день!!!

      Столкнулся с проблемой преобразования двух переменных типа byte в одну типа word.
      Ведь при переводе нужно указывать какой байт младший, а какой старший.
      Посоветуйте пожалуйста как решить эту проблему.

      Заранее спасибо.


      Булат Шакиров



      Сообщ.
      #2

      ,
      04.04.06, 07:59

        Слово := Старший_байт*256+Младший_байт;


        Coala



        Сообщ.
        #3

        ,
        04.04.06, 07:59

          Ну если у тебя первый ТВОЙ байт должен быть старшим, то можно так
          W = (B1 * 255) + B2
          ЗЫ — спешка нужна при ловле блох, конечно же
          W = (B1 * 256) + B2

          Сообщение отредактировано: Coala — 04.04.06, 08:03


          Albinos_X



          Сообщ.
          #4

          ,
          04.04.06, 08:04

            Full Member

            ***

            Рейтинг (т): 16

            ExpandedWrap disabled

              W:=(B1 Shl 8) + B2;

            Сообщение отредактировано: Albinos_X — 04.04.06, 08:06


            intaari



            Сообщ.
            #5

            ,
            04.04.06, 08:07

              Оззя
              Coala. Спасибо за ответы.

              Сообщение отредактировано: intaari — 04.04.06, 08:08


              Mechanic



              Сообщ.
              #6

              ,
              04.04.06, 13:52

                ExpandedWrap disabled

                  var Hb,LB: byte;

                      W: word; absolute Hb;

                  begin

                      Hb := $12;

                      Lb := $34;

                      writeln(‘$’+IntToHex(W,4));

                  end;

                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)

                0 пользователей:

                • Предыдущая тема
                • Delphi: Общие вопросы
                • Следующая тема

                Рейтинг@Mail.ru

                [ Script execution time: 0,0457 ]   [ 16 queries used ]   [ Generated: 13.04.23, 20:57 GMT ]  

                These functions are useful:

                function MakeWord(low, high: char): word;
                begin
                  result := byte(high) shl 8 + byte(low);
                end; 
                
                function MakeWord(low, high: byte): word;
                begin
                  result := high shl 8 + low;
                end; 
                

                However I am wondering if these kinds of functions (could be implemented differently) already exist somewhere (not in a windows api specific file, but rather a cross platform RTL function).

                Example use case: take the two characters GT and make a WORD result out of it.

                MakeWord('G','T');
                

                I find this more readable than inserting SHL/SHR AND/OR hex operations and other hacks in the code that do not describe what the code is doing… so surely these functions exist somewhere already? Or do people roll their own in their applications?

                Or something like:

                var x: word;
                begin
                  lo(x) := byte('G');
                  hi(x) := byte('T');
                end;
                

                However, that will not work as the left side cannot be assigned to: but it is more readable, than some other solutions, IMO.

                I think I have seen LoWord and HiWord functions too (or LoByte, HiByte) but usually in read only cases. What about writing to the hi and lo?

                #delphi #delphi-7

                #delphi #delphi-7

                Вопрос:

                Я разрабатываю проект с помощью Delphi и хочу преобразовать массив байтов в строковый тип. Как я могу это сделать?

                Примеры кодов C #:

                 private void ListenerOnDataTransmit(DataTransmitEventArgs e)
                {
                    transmittedMsg = BitConverter.ToString(e.TransmittedBytes, 0, e.TransmittedBytes.Length);
                    try { Invoke(new EventHandler(UpdateTransmittedMessagesListView)); }
                    catch { }
                }
                 

                Комментарии:

                1. Вы забыли сказать нам, что вы подразумеваете под «преобразованием массива байтов в строку». Существует несколько различных интерпретаций, все разумные: (1) обработайте массив байтов как ASCII и получите кодируемый им текст; (2) обработайте массив байтов как UTF8 и получите кодируемый им текст; (3) получите необработанное шестнадцатеричное представление массива данных; (4) получите необработанныйдвоичное представление массива данных; и т.д. В последних случаях вы хотите сгруппировать цифры?

                Ответ №1:

                BitConverter.ToString() Метод «Преобразует числовое значение каждого элемента указанного массива байтов в эквивалентное шестнадцатеричное строковое представление». Вы можете сделать то же самое вручную в Delphi 7, используя SysUtils.IntToHex() функцию в цикле, например:

                 uses
                  ..., SysUtils;
                
                var
                  bytes: array of byte;
                  s: string;
                  i: Integer;
                begin
                  bytes := ...;
                  s := '';
                  if bytes <> nil then
                  begin
                    s := IntToHex(bytes[0], 2);
                    for i := 1 to High(bytes) do
                      s := s   '-'   IntToHex(bytes[i], 2);
                  end;
                end;
                 

                Комментарии:

                1. Совершенно допустимо, но (очень) неэффективно для длинных буферов из-за постоянного перераспределения строки.

                2. @AndreasRejbrand Да, есть много разных способов подойти к этому. Выше приведен только один пример.

                3. Верно. И для небольших буферов это, безусловно, достаточно хорошо, так что 1.

                4. По крайней мере, теперь у нас есть действительно хороший Q amp; A, который мы можем использовать как канонический для закрытия дубликатов.

                5. @RemyLebeau Спасибо, я искал это.

                Ответ №2:

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

                Для этого я всегда использую следующую свою процедуру:

                 function BytesToString(ABuf: PByte; ALen: Cardinal): string; overload;
                const
                  HexDigits: array[0..$F] of Char = '0123456789ABCDEF';
                var
                   i: Integer;
                begin
                   if ALen = 0 then
                   begin
                     Result := '';
                     Exit;
                   end;
                   SetLength(Result, 3 * ALen - 1);
                   Result[1] := HexDigits[ABuf^ shr 4];
                   Result[2] := HexDigits[ABuf^ and $0F];
                   for i := 1 to ALen - 1 do
                   begin
                     Inc(ABuf);
                     Result[3*i   0] := ' ';
                     Result[3*i   1] := HexDigits[ABuf^ shr 4];
                     Result[3*i   2] := HexDigits[ABuf^ and $0F];
                   end;
                end;
                
                type
                  TByteArray = array of Byte;
                
                function BytesToString(ABytes: TByteArray): string; overload;
                begin
                  Result := BytesToString(PByte(ABytes), Length(ABytes));
                end;
                 

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

                Это очень быстрая реализация, поскольку я не использую конкатенацию строк (которая требует постоянных перераспределений кучи).


                Приведенный выше код был написан специально для старого компилятора Delphi 7 и RTL. Современная версия будет выглядеть примерно так:

                 function BytesToString(ABuf: PByte; ALen: Cardinal): string; overload;
                const
                  HexDigits: array[0..$F] of Char = '0123456789ABCDEF';
                var
                   i: Integer;
                begin
                   if ALen = 0 then
                    Exit('');
                   SetLength(Result, 3 * ALen - 1);
                   Result[1] := HexDigits[ABuf[0] shr 4];
                   Result[2] := HexDigits[ABuf[0] and $0F];
                   for i := 1 to ALen - 1 do
                   begin
                     Result[3*i   0] := ' ';
                     Result[3*i   1] := HexDigits[ABuf[i] shr 4];
                     Result[3*i   2] := HexDigits[ABuf[i] and $0F];
                   end;
                end;
                
                function BytesToString(ABytes: TArray<Byte>): string; overload;
                begin
                  Result := BytesToString(PByte(ABytes), Length(ABytes));
                end;
                 

                Приведенный выше код группирует каждый байт с использованием символа пробела. Конечно, вы можете этого не хотеть, но выполнение этого без группировки — более простая задача, поэтому я оставлю это как упражнение.

                Комментарии:

                1. Честно говоря, я действительно чесал голову, когда увидел 3 * ALen … То есть, пока я не увидел пробел.

                2. PByte Математика ptr на основе IIRC недоступна в Delphi 7, поэтому я заменил ее еще несколькими методами старой школы.


                Форум программистов Vingrad

                Модераторы: Poseidon, Snowy, bems, MetalFan

                Поиск:

                Ответ в темуСоздание новой темы
                Создание опроса
                > Два Byte в Word Не сложение!!! 

                V

                   

                Опции темы

                RinOSpro
                Дата 19.6.2008, 11:55 (ссылка)
                   |    (голосов: 0)
                Загрузка ... Загрузка …




                Быстрая цитата

                Цитата

                Unregistered

                Есть скажем 2 байтовых переменных и переменная Word и нужно пометить один байт в старший разряд а другой в младший разряд. (не сложить!);
                Я сделал это таким споссобом:

                Код

                var
                  b1, b2 : byte;
                  w : word;
                begin
                ...
                  b1 := $01;
                  b1 := $47;
                  w := (b1 *$FF) + b2;
                ...
                end;

                Есть ли другие споссобы?

                  Вверх
                Snowy
                Дата 19.6.2008, 12:33 (ссылка)
                | (нет голосов)
                Загрузка ... Загрузка …




                Быстрая цитата

                Цитата

                Эксперт
                ****

                Профиль
                Группа: Модератор
                Сообщений: 11363
                Регистрация: 13.10.2004
                Где: Питер

                Репутация: 192
                Всего: 484

                Логическими операциями или вариантной записью.
                Логическими логичнее smile

                Код

                  w := b1 shl 8 or b2;

                PM MAIL   Вверх
                Beltar
                Дата 19.6.2008, 13:08 (ссылка)
                | (нет голосов)
                Загрузка ... Загрузка …




                Быстрая цитата

                Цитата

                Опытный
                **

                Профиль
                Группа: Участник
                Сообщений: 627
                Регистрация: 11.1.2006

                Репутация: 3
                Всего: 7

                Еще один извращенский вариант использовать указатели. smile Но это для справки, т. к. варианты Snowy короче. smile

                ———————

                Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
                Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.

                PM MAIL   Вверх
                Virtuals
                Дата 19.6.2008, 13:11 (ссылка)
                | (нет голосов)
                Загрузка ... Загрузка …




                Быстрая цитата

                Цитата

                Опытный
                **

                Профиль
                Группа: Участник
                Сообщений: 476
                Регистрация: 27.11.2006

                Репутация: 3
                Всего: 11

                извращения с волшебной палочкой ABSOLUTE но возможностей куча. тоесть вообще никаких операций не нужно делать ни сдвигов ни умножения, а просто обьявить переменные в одних и тех же местах smile

                Код

                var W:word;
                    B:array[0..1] of Byte absolute w;

                    begin
                    W:=$0000;
                    writeln(hexW(W));

                b[0]:=10;
                b[1]:=20;

                    writeln(hexW(W));
                    end.

                Это сообщение отредактировал(а) Virtuals — 19.6.2008, 13:43

                PM MAIL ICQ   Вверх
                Virtuals
                Дата 19.6.2008, 13:28 (ссылка)
                | (нет голосов)
                Загрузка ... Загрузка …




                Быстрая цитата

                Цитата

                Опытный
                **

                Профиль
                Группа: Участник
                Сообщений: 476
                Регистрация: 27.11.2006

                Репутация: 3
                Всего: 11

                .
                а как удалять сообщения? smile

                Это сообщение отредактировал(а) Virtuals — 19.6.2008, 13:35

                PM MAIL ICQ   Вверх
                Snowy
                Дата 19.6.2008, 13:59 (ссылка)
                | (нет голосов)
                Загрузка ... Загрузка …




                Быстрая цитата

                Цитата

                Эксперт
                ****

                Профиль
                Группа: Модератор
                Сообщений: 11363
                Регистрация: 13.10.2004
                Где: Питер

                Репутация: 192
                Всего: 484

                Цитата(Virtuals @  19.6.2008,  13:28 Найти цитируемый пост)
                а как удалять сообщения?

                Никак.
                Только участники Клуба и выше имеют такую возможность.

                PM MAIL   Вверх
                RinOSpro
                Дата 19.6.2008, 14:14 (ссылка)
                   |    (голосов: 0)
                Загрузка ... Загрузка …




                Быстрая цитата

                Цитата

                Unregistered

                Snowy  ты уверен что это точнее я так делал… но отказался в пользу умножения. тк. что то это глючило помоему хотя хз…

                В общем спасибо! Щас выберу оптимальный вариант.

                Добавлено через 10 минут и 27 секунд
                Сорь… я у себя проглядел и вместо or поставил and поэтому понятно почему глючило…

                  Вверх
                Snowy
                Дата 19.6.2008, 14:26 (ссылка)
                | (нет голосов)
                Загрузка ... Загрузка …




                Быстрая цитата

                Цитата

                Эксперт
                ****

                Профиль
                Группа: Модератор
                Сообщений: 11363
                Регистрация: 13.10.2004
                Где: Питер

                Репутация: 192
                Всего: 484

                Моя запись идентична твоей. Только работает быстрее и работает правильно.
                Рассмотрим поотдельности.
                w := (b1 *$FF) + b2;
                b1 *$FF — тут у тебя ошибка. Умножать нужно на $100.
                Суди сам. Допустим b1 = 1, тогда b1 * $FF = $FF, что есть $00FF, а не $0100
                Разумеется, при таком сдвиге, наложение нижнего байта будет давать полную ересь.
                b1 *$100 = сдвигу на 8 байт вверх. Точнее влево.
                $XX00 + $YY — сложение здесь не требуется, ибо у исходного числа нижние байты пустые, а у прибавляемого нет верхних байтов.
                Таким образом быстрее проще наложить нижние байты второго, вместо нижних первого.
                А разница будет, т.к. в твоём коде 2 ошибки:
                1. Не присвоено b2
                2. Неверно выполнен сдвиг первого байта.
                А для проверки правильности, выполни IntToHex(w, 2) и выведи результат на экран.

                PM MAIL   Вверх
                Alexeis
                Дата 19.6.2008, 14:30 (ссылка)
                | (нет голосов)
                Загрузка ... Загрузка …




                Быстрая цитата

                Цитата

                Амеба
                Group Icon

                Профиль
                Группа: Админ
                Сообщений: 11743
                Регистрация: 12.10.2005
                Где: Зеленоград

                Репутация: 109
                Всего: 459

                Директиву absolute, не желательно использовать, так как это усложнит перенос на Delphi.NET. По крайней мере Codeger не рекомендует ее использовать.

                Вообще, красивее будет так

                Код

                  w := (word(b1) shl 8) or b2;

                Дело в том что чисто логически b1 shl 8 должен дать 0, потому что операнд 8ми битовый, но компилятор оптимизирует вычисления расширяя байтовые операнды до 32х битовых слов, потому это будет работать.

                ———————

                Vit вечная память.

                Обсуждение действий администрации форума производятся только в этом форуме

                гениальность идеи состоит в том, что ее невозможно придумать

                PM ICQ Skype   Вверх



















                Ответ в темуСоздание новой темы
                Создание опроса
                Правила форума «Delphi: Общие вопросы»
                SnowyMetalFan
                bemsPoseidon
                Rrader

                Запрещается!

                1. Публиковать ссылки на вскрытые компоненты

                2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

                • Литературу по Дельфи обсуждаем здесь
                • Действия модераторов можно обсудить здесь
                • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
                • Вопросы по реализации алгоритмов рассматриваются здесь
                • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) — крупнейшем в рунете сборнике материалов по Дельфи


                Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

                 

                0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
                0 Пользователей:
                « Предыдущая тема | Delphi: Общие вопросы | Следующая тема »

                Понравилась статья? Поделить с друзьями:
              • Calculate of a number in excel
              • Byte address and word address
              • Calculate number of days excel
              • By word or dead перевод
              • Calculate not working excel