Recent

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

Jonvy

  • Jr. Member
  • **
  • Posts: 90
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

  • Hero Member
  • *****
  • Posts: 4219
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.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Thaddy

  • Hero Member
  • *****
  • Posts: 14201
  • Probably until I exterminate Putin.
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 »
Specialize a type, not a var.

Leledumbo

  • Hero Member
  • *****
  • Posts: 8746
  • 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: 69
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: 14201
  • Probably until I exterminate Putin.
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.

Specialize a type, not a var.

lucamar

  • Hero Member
  • *****
  • Posts: 4219
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 »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

engkin

  • Hero Member
  • *****
  • Posts: 3112
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

  • Hero Member
  • *****
  • Posts: 4219
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 »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

engkin

  • Hero Member
  • *****
  • Posts: 3112
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.

 

TinyPortal © 2005-2018