Lazarus

Programming => General => Topic started by: Jonvy on August 10, 2018, 03:00:49 pm

Title: How to convert byte data to float(4 bytes)?
Post by: Jonvy on August 10, 2018, 03:00:49 pm
My program received in buffer a float data, single type in 4 bytes,the 4 bytes are 3,  65,  83,  51, integer type,how can I get the float value of  these 4 bytes?

It looks TextToFloat can do int, but I don't know how to use it, can anyone help me?

Thanks!
Title: Re: How to convert byte data to float(4 bytes)?
Post by: lucamar on August 10, 2018, 03:13:25 pm
Hmmm ... old school solution?

Code: [Select]
function ConvertToSingle(Data: array[0..3] of byte): Single;
var
  ASingle: Single absolute Data;
begin
  Result := ASingle;
end;

But I'm sure there are easier and more secure ways.
Title: Re: How to convert byte data to float(4 bytes)?
Post by: Thaddy on August 10, 2018, 04:22:12 pm
If the buffer is declared as of type single array, you can simply read it directly. Mind you: byte order can play dirty tricks here.
But anyway a cardinal or a longword can be converted like this:
Code: Pascal  [Select][+][-]
  1. uses sysutils;
  2. var
  3.   buffer:array[0..bufsize_in_4byte_steps-1] of cardinal;
  4.   s:single;
  5. begin
  6.   s := Buffer[0].ToSingle; //first element... etc.
Title: Re: How to convert byte data to float(4 bytes)?
Post by: Leledumbo on August 10, 2018, 05:19:49 pm
Hmmm ... old school solution?

Code: [Select]
function ConvertToSingle(Data: array[0..3] of byte): Single;
var
  ASingle: Single absolute Data;
begin
  Result := ASingle;
end;

But I'm sure there are easier and more secure ways.
With the exception of possible endianness mismatch (which can be easily solved by applying System.BEToN or System.LEToN to another absolut alias of type LongWord/LongInt), this is the best solution IMO.
Title: Re: How to convert byte data to float(4 bytes)?
Post by: Gammatester on August 10, 2018, 05:22:13 pm
If the buffer is declared as of type single array, you can simply read it directly. Mind you: byte order can play dirty tricks here.
But anyway a cardinal or a longword can be converted like this:
Code: Pascal  [Select][+][-]
  1. uses sysutils;
  2. var
  3.   buffer:array[0..bufsize_in_4byte_steps-1] of cardinal;
  4.   s:single;
  5. begin
  6.   s := Buffer[0].ToSingle; //first element... etc.
I doubt that `cardinal.tosingle` is what is wanted. IMO `cardinal.tosingle` simply converts the integer value to a single and does not map the floating point structure. Here  the values from the OP
Code: Pascal  [Select][+][-]
  1. uses
  2.   sysutils;
  3. const
  4.   b: packed array[0..3] of byte = (3,  65,  83,  51);
  5. var
  6.   s: single absolute b;
  7.   c: cardinal absolute b;
  8. begin
  9.   writeln(s);
  10.   writeln(c);
  11.   writeln(c.tosingle);
  12. end.
  13.  
and the result
Code: Diff  [Select][+][-]
  1.  4.918639362E-08
  2. 861094147
  3.  8.610941440E+08
Title: Re: How to convert byte data to float(4 bytes)?
Post by: Thaddy on August 10, 2018, 05:28:39 pm
Well... I combine Leledumbo's suggestion, my warning and your ignorance in a simple example..
It does not matter if you use absolute or not. You should be aware of endianness.
Code: Pascal  [Select][+][-]
  1. {$ifdef fpc}{$mode delphi}{$H+}{$endif}
  2. uses sysutils;
  3. var
  4.   a: array[0..3] of byte =($0F,$FF,$00,$01);
  5.   b: single;
  6.   c: cardinal;
  7. begin
  8.   b:=psingle(@a)^;
  9.   writeln(b);
  10.   c:=PCardinal(@b)^;
  11.   writeln('$',beton(c).ToHexString(8));  
  12.   writeln('$',c.ToHexString(8));
  13. end.

Title: Re: How to convert byte data to float(4 bytes)?
Post by: lucamar on August 10, 2018, 08:26:21 pm
It does not matter if you use absolute or not. You should be aware of endianness.

Yes, of course. Maybe this version is better ...

Code: Pascal  [Select][+][-]
  1. function ConvertToSingle(Data: packed array[0..3] of Byte; EndianSwap: Boolean= False): Single;
  2. var
  3.   i: Integer;
  4.   TheBytes: packed array[0..3] of Byte;
  5.   ASingle: Single absolute TheBytes;
  6. begin
  7.   if EndianSwap then
  8.     for i := 0 to 3 do
  9.        TheBytes[Abs(3 - i)] := Data[i]
  10.   else
  11.     for i := 0 to 3 do
  12.       TheBytes[i] := Data[i];
  13.   Result := ASingle;
  14. end;
  15.  

Just a q&d example, mind you. I tend to avoid absolute normally, but sometimes it seems to be the most natural way to code something. Although Thaddy's pointer-casting is quite a nice thing too. :)
Title: Re: How to convert byte data to float(4 bytes)?
Post by: engkin on August 10, 2018, 08:58:50 pm
Code: Pascal  [Select][+][-]
  1.   if EndianSwap then
You can use SwapEndian:
Code: Pascal  [Select][+][-]
  1. function ConvertToSingle(const Data; EndianSwap: Boolean=False):Single;inline;
  2. var
  3.   ASingle: Single absolute Data;
  4.   ADWord: DWord absolute Result;
  5. begin
  6.   Result := ASingle;
  7.   if EndianSwap then
  8.     ADWord := SwapEndian(ADWord)
  9. end;
Title: Re: How to convert byte data to float(4 bytes)?
Post by: lucamar on August 10, 2018, 09:18:05 pm
Code: Pascal  [Select][+][-]
  1.   if EndianSwap then
You can use SwapEndian.

It's just a parameter name; it may as well be called DoTheSwapDance for all it matters  :D

If you mean using System.SwapEndian(), you're, o.c., absolutely right. Third try:

Code: Pascal  [Select][+][-]
  1. function ConvertToSingle(Data: packed array[0..3] of Byte; EndianSwap: Boolean= False): Single;
  2. var
  3.   ASingle: Single absolute Data;
  4. begin
  5.   if EndianSwap then
  6.     // SwapEndian(PDWord(@Data)^); {corrected; was: PQWord(@Data) Tremendous error!}
  7.   { In fact, this *should* work even better }
  8.   SwapEndian(DWord(Data));
  9.   Result := ASingle;
  10. end;
  11.  

* Edited to quash a couple errors ... an then to add a replacement
Title: Re: How to convert byte data to float(4 bytes)?
Post by: engkin on August 10, 2018, 09:24:23 pm
Code: Pascal  [Select][+][-]
  1.   if EndianSwap then
You can use SwapEndian.

It's just a parameter name; it may as well be called DoTheSwapDance for all it matters  :D
LOL, no not the name.
TinyPortal © 2005-2018