* * *

Author Topic: How to convert byte data to float(4 bytes)?  (Read 284 times)

Jonvy

  • New member
  • *
  • Posts: 14
How to convert byte data to float(4 bytes)?
« 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!

lucamar

  • New member
  • *
  • Posts: 35
Re: How to convert byte data to float(4 bytes)?
« Reply #1 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.
Been there, done that ... barely kept the project timelines. ;)

Thaddy

  • Hero Member
  • *****
  • Posts: 6519
Re: How to convert byte data to float(4 bytes)?
« Reply #2 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.
« Last Edit: August 10, 2018, 04:29:13 pm by Thaddy »
Ada's daddy wrote this:"Fools are my theme, let satire be my song."

Leledumbo

  • Hero Member
  • *****
  • Posts: 7936
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: How to convert byte data to float(4 bytes)?
« Reply #3 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.

Gammatester

  • Jr. Member
  • **
  • Posts: 54
Re: How to convert byte data to float(4 bytes)?
« Reply #4 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

Thaddy

  • Hero Member
  • *****
  • Posts: 6519
Re: How to convert byte data to float(4 bytes)?
« Reply #5 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.

Ada's daddy wrote this:"Fools are my theme, let satire be my song."

lucamar

  • New member
  • *
  • Posts: 35
Re: How to convert byte data to float(4 bytes)?
« Reply #6 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. :)
« Last Edit: August 10, 2018, 08:31:14 pm by lucamar »
Been there, done that ... barely kept the project timelines. ;)

engkin

  • Hero Member
  • *****
  • Posts: 2082
Re: How to convert byte data to float(4 bytes)?
« Reply #7 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;
« Last Edit: August 10, 2018, 09:22:36 pm by engkin »

lucamar

  • New member
  • *
  • Posts: 35
Re: How to convert byte data to float(4 bytes)?
« Reply #8 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
« Last Edit: August 10, 2018, 09:43:45 pm by lucamar »
Been there, done that ... barely kept the project timelines. ;)

engkin

  • Hero Member
  • *****
  • Posts: 2082
Re: How to convert byte data to float(4 bytes)?
« Reply #9 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.

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus