1

Hi I am trying to convert the hex value into float the method I am using is

function hex2float($strHex) {
$hex = sscanf($strHex, "%02x%02x%02x%02x%02x%02x%02x%02x");
$hex = array_reverse($hex);
$bin = implode('', array_map('chr', $hex));
$array = unpack("dnum", $bin);
return $array['num'];
}

$float = hex2float('4019999a');
echo $float;

Output

The output it's returning is 6.4000015258789 but in actual it should be 2.4

See reference

Moeez
  • 494
  • 9
  • 55
  • 147
  • 2
    I vote to reopen this as the question isn't actually about precision. It's about little endian versus big endean byte order. – Sherif Apr 15 '20 at 18:02
  • The representation here can be either 2.4 or 6.33 depending on endianess. For example, `var_dump(unpack('G*', hex2bin('4019999a'))[1]);` gives you `float(2.4000000953674)` whereas `var_dump(unpack('g*', hex2bin('4019999a'))[1]);` would give you `float(-6.3320110435437E-23)`. One is little endian and the other is big endian. – Sherif Apr 15 '20 at 18:04
  • @Sherif how can I get exact `2.4` as this value is sent from the client machine? – Moeez Apr 16 '20 at 04:32
  • There is no such thing as exactly value in floating point math. This is why we have precision settings. A single precision float only has 7 digits of precision whereas a double precision float (what PHP casts the value to internally) has 15 digits of precision. You took a single precision float and stored it in a double precision float. The extra digits come from the fact that your single precision float is too small fit in a double precision float. Notice there are exactly 6 zeros after the 4 there. – Sherif Apr 16 '20 at 09:52

1 Answers1

1

Your problem is that you are interpreting the value in little endian byte order. This gives you the incorrect value of 6.4, which is actually -6.3320110435437E-23. Additionally, you are unpacking this as a double-precision float. It's not. It's single precision (only 4 bytes wide).

function hex2float($strHex) {
    $hex = sscanf($strHex, "%02x%02x%02x%02x%02x%02x%02x%02x");
    $bin = implode('', array_map('chr', $hex));
    $array = unpack("Gnum", $bin);
    return $array['num'];
}

$float = hex2float('4019999a');
echo $float;

This gives you the correct value of 2.4.

An easier way to do this is var_dump(unpack('G', hex2bin('4019999a'))[1]); which also gives you the correct value.

Sherif
  • 11,786
  • 3
  • 32
  • 57
  • Using `sscanf()` and `implode()` is unnecessary, you can just `$bin = hex2bin($strHex);` directly. – Sammitch Apr 15 '20 at 19:08
  • @Sherif the value I am getting is `2.4000000953674`, but the actual value passed from the client is `2.4` – Moeez Apr 15 '20 at 20:15
  • 1
    Yes, they're the same value. `2.4000000953674` rounds to `2.4`. Welcome to floating point arithmetic. – Sherif Apr 16 '20 at 09:39