Rayaarito
Rayaarito

Reputation: 410

Convert array of values into a single float value in PHP?

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

Upvotes: 3

Views: 1846

Answers (4)

slevy1
slevy1

Reputation: 3820

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.

Upvotes: 1

Goldbug
Goldbug

Reputation: 605

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

Upvotes: 1

Rajdeep Paul
Rajdeep Paul

Reputation: 16963

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

Upvotes: 2

FonzTech
FonzTech

Reputation: 408

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.

Upvotes: 0

Related Questions