3

I have an array with these values (when the array is printed with print_r();

Array:
[0] => 66 
[1] => 233
[2] => 204
[3] => 205

The values in hex are:

Array:
[0] => 0x42 
[1] => 0xE9
[2] => 0xCC
[3] => 0xCD

What I'm looking to do is to turn this 4 byte array into a float value. If I use implode(); to turn the array into a value, it just combines the string into 66233204205 instead of 0x42E9CCCD which are not similar. Thus I can't use floatval(). PHP is new to me, and so is using string values instead of the actual bits, like I can in C.

What I'm thinking is to some how implode() it with the hex values, instead of those integer numbers, and then use floatval().

Any ideas guys?

EDIT:

Just so it's a little clearer, I should be obtaining 116.900 as the result

Rayaarito
  • 400
  • 4
  • 21
  • Are you looking to sum the values or just append the values of the array one after the next? – Goldbug Aug 12 '17 at 20:26
  • @Goldbug, thanks for responding so fast! I'm looking to append the values of the array one after the next (in hex) and then convert it to a float. If I use `implode();` to append it, it appends it in its string value; which would look like `66233204205` – Rayaarito Aug 12 '17 at 20:28
  • Sounds like `array_map('dechex', $array)`, then `implode()` then `hexdec()`. But I didn't test it, and I think it will fail for bigger numbers. – jh1711 Aug 12 '17 at 20:34
  • 1
    Thanks @slevy1. I must have focused on the `0x42E9CCC` string without realizing that it didn't get us any closer to the solution. At least the edit was a few minutes after my comment :) – jh1711 Aug 16 '17 at 21:25

4 Answers4

2

You have to do a simple math operation to concatenate hex values of the array one after the other. The algorithm would be like this:

  • Assign the first hex value of the array to a resultant variable, $concat in this case.
  • Use a for loop to loop through the array from 2nd element till nth element
  • In each iteration of the loop left shift 8 times the existing hex value of the resultant variable and place the new hex value in the least significant 8 bits of the resultant variable.

    // Suppose $array is your original array
    $concat = $array[0];
    $count = count($array);
    for($i = 1; $i < $count; $i++){
        $concat =  ($concat << 8) + $array[$i];
    }
    
    // display concatenated hex value: 42e9cccd
    var_dump(dechex($concat));
    
    // Now do your operation on the concatenated hex value
    

Here's a demo, https://eval.in/844793

Rajdeep Paul
  • 16,887
  • 3
  • 18
  • 37
1

This appends the values of the array to eachother (in hexadecimal). PHP's dechex() function.

http://php.net/dechex

dechex — Decimal to hexadecimal

$b = [66,233,204,205];
$a = dechex($b[0]);
for($x = 1; $x < count($b); $x++) {
    $a = $a . dechex($b[$x]);
}
echo $a; // $a = 42e9cccd
Goldbug
  • 605
  • 6
  • 8
1

Revised Answer with ....

Performing math with hex strings used to be a feature supported in PHP. Now with PHP 7, a hex string only represents a string of characters and no longer is recognized as containing a numeric value. If you attempt to do math with it, the result is zero. Consider the following code:

 <?php  

 $arr = [66, 233, 204, 205];

 $res = array_reduce( $arr, function($c,$i) {
                   $c.=dechex( $i );
                   return $c;
 });

 $temp = "0x" . $res;  // 0x42e9cccd
 var_dump($temp + 0);

See demo

This code attempts to provide the hex string a mathematical context by adding zero to the value contained in $temp. This code works until PHP 7 because the powers that be determined that hexstrings created more problems than they were worth; see this RFC and the Manual:"Hexadecimal strings are no longer considered numeric".

Concatenation, being a string operation, creates the example's hex string whose direct usage proves unwise in a math operation. A notice will be emitted (in PHP 7.1), complaining as follows:

Notice: A non well formed numeric value encountered

You may suppress displaying this notice, but the resulting sum will be zero in PHP 7. When the code functions correctly in PHP 5.6, the result of 1122618573 seems wrong, certainly far too large to cast as a float and obtain the value that the OP seeks.

... A Bona Fide Work-Around

    <?php


    $arr = [66, 233, 204, 205];
    $res = array_reduce( $arr, function($c,$i) {
                       $c.=dechex( $i );
                       return $c;
    });
    $temp = "0x" . $res;
    $int = filter_var( $temp, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX );
    if (false === $int) {
        throw new Exception("Invalid integer!");
    }


    $arr = (unpack('f', pack('i', $int )));
    $f = array_pop($arr);
    printf("%.3f",$f);    

See demo

PHP will recognize the numeric hex string that array_reduce() yields if you use filter_var() with the indicated parameters. In this fashion, you may obtain an integer evaluating as 1122618573. The key thing rather than the integer's value is its binary bit pattern. Borrowing from the official answer here, the code needs to pack $int into a binary string, which it subsequently will unpack as a float -- almost. That result will be returned as an array with just one element. After popping off and capturing that element's float value, printf() displays 116.900.

slevy1
  • 3,797
  • 2
  • 27
  • 33
  • 1
    Thank you for this very detailed response. When I give this a shot it shows the `1122618573` value since I'm running on a 64-bit machine. Is there a way around that to get it to show its true intended value `116.900`? The other answers are able to show 116.900. Which is strange considering I'm on a 64-bit machine. – Rayaarito Aug 14 '17 at 14:13
  • @Rayaarito: In answer to your question, yes, there is a work-around; please see my updated answer. – slevy1 Aug 17 '17 at 09:19
  • 1
    thanks for the work around. I did use the other ones just because it worked for the version I have and I already put it in my code. But, I marked yours correct because it's "future-proof". So when people come to this question later on, they know your answer will work no matter what because its for the latest generation of PHP. Which is v 7.1.8 as of this writing. Thank you! – Rayaarito Aug 17 '17 at 17:28
0

You didn't specify if your array represents an integer, if is the integer part of the floating point value, or is the entire number represented in IEEE 754 format. Anyway, I would suggest you to take a look at the "pack" function.

$value = pack('i', your_value);

HERE you can find the documentation: basically you have to provide the type you want to obtain, along with your value(s), of course. Also PHP is NOT a strongly typed language, so you don't have to distinguish integer from floats, in this case. You can treat integer like floats, and viceversa. But if you want to be 100% sure, just do something like this:

$value = floatval(pack('i', your_value));

This is, of course, machine dependent, but I don't know of any machine running PHP that doesn't use IEEE 754 floats.

FonzTech
  • 408
  • 1
  • 5
  • 13