1

The following is a list of hex data and the float numbers it represents:

e77ed8f8201a5440 = 78.4083
0000000000005540 = 82
4c541773e2185040 = 62.3888
0000000000005640 = 86

The following Perl code uses pack/unpack to gets the conversion almost right (out by exactly 2):

use strict;
use warnings;

while (<DATA>)
{
   chomp;
   my $dat = $_;
   my $hval = pack "H*", $dat;
   my $fval = unpack "F", $hval;
   print "$dat .. $fval \n";
}

__DATA__
e77ed8f8201a5440
0000000000005540
4c541773e2185040
0000000000005640

Output:

e77ed8f8201a5440 .. 80.408262454435
0000000000005540   .. 84
4c541773e2185040  .. 64.3888213851762
0000000000005640 .. 88

What is the Qt/C equivalent of this pack/unpack, or what is the algorithm it is use to "convert" the hex to float so I can that up instead?

TenG
  • 3,843
  • 2
  • 25
  • 42

2 Answers2

1

pack 'H*' is the conversion from hex character pairs to the corresponding bytes.

unpack 'F' is a cast to a double. This can be done using memcpy (to avoid alignment issues), as shown below:

#include <stdio.h>
#include <string.h>

int main() {
   char bytes[] = { 0xE7, 0x7e, 0xd8, 0xf8, 0x20, 0x1a, 0x54, 0x40 };

   double d;
   memcpy(&d, bytes, sizeof(bytes));

   printf("%lf\n", d);
   return 0;
}

Output:

$ gcc -o a a.c && a
80.408262

Note that this will fail on big-endian machines. You'll have to reverse the bytes before copying them on those machines.

Community
  • 1
  • 1
ikegami
  • 367,544
  • 15
  • 269
  • 518
1

What is the Qt/C equivalent of this pack/unpack,

#include <QString>
#include <QByteArray>
#include <algorithm>
#include <cstring>

...

QString value="e77ed8f8201a5440";
// convert the hex string to an array of bytes
QByteArray arr=QByteArray::fromHex(value);
// reverse if necessary
#if Q_BYTE_ORDER==Q_BIG_ENDIAN
std::reverse(arr.begin(), arr.end());
#endif
// if everything went right, copy the bytes in a double
if(arr.size()==sizeof(double))
{
    double out;
    std::memcpy((void *)&out, (void *)arr.data(), sizeof(double));
    // ...
}

Maybe you could also get away with QtEndian (instead of conditionally calling std::reverse over arr), but it's not clear if those functions can be called on anything but integral types.

or what is the algorithm it is use to "convert" the hex to float so I can that up instead?

The data you have is just the dump of the raw content of a little-endian IEEE-754 double; the "algorithm" is simply decoding the hexadecimal to the bytes it represents and copying them to a double variable (reversing the byte order if we are on a big-endian machine).

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • @ikegami: uh sorry, you are right, I don't know why I continued to think they were floats. – Matteo Italia May 31 '14 at 19:59
  • Thanks - the data I am reading is from a QByteArray so this answers is exactly what I need. Many thanks. – TenG May 31 '14 at 20:22
  • @TenG: in that case, keep in mind that, if your `QByteArray` contains more stuff than just one single `double`, the `reverse` must be applied on 8-byte chunks (and not on the whole QByteArray`). – Matteo Italia May 31 '14 at 20:25