PHP convert hex to float - php

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

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.

Related

PHP Math fail (hexadecimal)

Im trying to do a php multiplication of two 32bit long hexadecimal valuey with PHP and it seems it is messing up this calculation, the same happens if i multiplicate it as decimal value.
The calculation is as example:
0xB5365D09 * 0xDEBC252C
Converting to decimal before with hexdec doesnt change anything.
The expected result should be 0x9DAA52EA21664A8C but PHPs result is 0x9DAA52EA21664800
Example:
<?php
$res = 0xB5365D09 * 0xDEBC252C;
echo dechex(intval($res));
?>
What i am doing wrong here?
PHP8.2 running on debian, 64bit AMD.
So, for others to find the answer:
Someone stated in the comments to my question, that the result is above the PHP_MAX_INT limit. So when PHP handle it as a FLOAT, there will be some precision of the result lost. I got it to work using bcmath. In my case, i didnt do math with the result any further so i grabbed some piece of code from here, and made a simple function which does what i need. Here you can see a minimum-example:
function bcmul_hex($h1, $h2) {
$dec = bcmul($h1, $h2);
$hex = '';
do {
$last = bcmod($dec, 16);
$hex = dechex($last).$hex;
$dec = bcdiv(bcsub($dec, $last), 16);
} while($dec>0);
return $hex;
}
echo bcmul_hex(0xB5365D09, 0xDEBC252C);
Here is a live example.
If you're trying to perform a mathematical operation on a hexadecimal value in PHP, you can use the hexdec function to convert the hexadecimal value to a decimal value, perform the operation, and then use the dechex function to convert the result back to a hexadecimal value.
Here's an example:
<?php
$hex1 = "B5365D09";
$hex2 = "DEBC252C";
// Convert hexadecimal values to decimal
$dec1 = hexdec($hex1);
$dec2 = hexdec($hex2);
// Perform multiplication operation
$result = $dec1 * $dec2;
// Convert result back to hexadecimal
$hex_result = dechex($result);
// Print result
echo "Result: $hex_result\n";
This code will output the result of the multiplication as a hexadecimal value.

php convert decimal to hexadecimal

I am extracting a serial from a digital certificate using the built-in OpenSSL library, however, I am having trouble converting this number to hex with precision.
The extracted number is originally in decimal but I need to have it in hex.
The number I am trying to convert is: 114483222461061018757513232564608398004
Here is what I've tried:
dechex() did not work, it returns: 7fffffffffffffff
The closest I could get was this function from the php.net page but it does not convert the whole number on part of it.
function dec2hex($dec) {
$hex = ($dec == 0 ? '0' : '');
while ($dec > 0) {
$hex = dechex($dec - floor($dec / 16) * 16) . $hex;
$dec = floor($dec / 16);
}
return $hex;
}
echo dec2hex('114483222461061018757513232564608398004');
//Result: 5620aaa80d50fc000000000000000000
Here is what I am expecting:
Decimal number: 114483222461061018757513232564608398004
Expected hex: 5620AAA80D50FD70496983E2A39972B4
I can see the correction conversion here:
https://www.mathsisfun.com/binary-decimal-hexadecimal-converter.html
I need a PHP solution.
The problem is that The largest number that can be converted is ... 4294967295 - hence why it's not working for you.
This answer worked for me during a quick test, assuming you have bcmath installed on your server, and you can obtain the number as a string to start with. If you can't, i.e. it begins life as numeric variable, you'll immediately reach PHP's float limit.
// Credit: joost at bingopaleis dot com
// Input: A decimal number as a String.
// Output: The equivalent hexadecimal number as a String.
function dec2hex($number)
{
$hexvalues = array('0','1','2','3','4','5','6','7',
'8','9','A','B','C','D','E','F');
$hexval = '';
while($number != '0')
{
$hexval = $hexvalues[bcmod($number,'16')].$hexval;
$number = bcdiv($number,'16',0);
}
return $hexval;
}
Example:
$number = '114483222461061018757513232564608398004'; // Important: already a string!
var_dump(dec2hex($number)); // string(32) "5620AAA80D50FD70496983E2A39972B4"
Ensure you pass a string into that function, not a numeric variable. In the example you provided in the question, it looks like you can obtain the number as a string initially, so should work if you have bc installed.
Answered by lafor.
How to convert a huge integer to hex in php?
function bcdechex($dec)
{
$hex = '';
do {
$last = bcmod($dec, 16);
$hex = dechex($last).$hex;
$dec = bcdiv(bcsub($dec, $last), 16);
} while($dec>0);
return $hex;
}
Example:
$decimal = '114483222461061018757513232564608398004';
echo "Hex decimal : ".bcdechex($decimal);
This is a big integer, so you need to use a big-integer library like GMP:
echo gmp_strval('114483222461061018757513232564608398004', 16);
// output: 5620aaa80d50fd70496983e2a39972b4
Try this 100% working for any number
<?php
$dec = '114483222461061018757513232564608398004';
// init hex array
$hex = array();
while ($dec)
{
// get modulus // based on docs both params are string
$modulus = bcmod($dec, '16');
// convert to hex and prepend to array
array_unshift($hex, dechex($modulus));
// update decimal number
$dec = bcdiv(bcsub($dec, $modulus), 16);
}
// array elements to string
echo implode('', $hex);
?>

64-bit Float Literals PHP

I'm trying to convert a 64-bit float to a 64-bit integer (and back) in php. I need to preserve the bytes, so I'm using the pack and unpack functions. The functionality I'm looking for is basically Java's Double.doubleToLongBits() method. http://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#doubleToLongBits(double)
I managed to get this far with some help from the comments on the php docs for pack():
function encode($int) {
$int = round($int);
$left = 0xffffffff00000000;
$right = 0x00000000ffffffff;
$l = ($int & $left) >>32;
$r = $int & $right;
return unpack('d', pack('NN', $l, $r))[1];
}
function decode($float) {
$set = unpack('N2', pack('d', $float));
return $set[1] << 32 | $set[2];
}
And this works well, for the most part...
echo decode(encode(10000000000000));
100000000
echo encode(10000000000000);
1.1710299640683E-305
But here's where it gets tricky...
echo decode(1.1710299640683E-305);
-6629571225977708544
I have no idea what's wrong here. Try it for yourself: http://pastebin.com/zWKC97Z7
You'll need 64-bit PHP on linux. This site seems to emulate that setup: http://www.compileonline.com/execute_php_online.php
$x = encode(10000000000000);
var_dump($x); //float(1.1710299640683E-305)
echo decode($x); //10000000000000
$y = (float) "1.1710299640683E-305";
var_dump($y); //float(1.1710299640683E-305)
echo decode($y); //-6629571225977708544
$z = ($x == $y);
var_dump($z); //false
http://www.php.net/manual/en/language.types.float.php
... never trust
floating number results to the last digit, and do not compare floating
point numbers directly for equality. If higher precision is necessary,
the arbitrary precision math functions and gmp functions are
available. For a "simple" explanation, see the » floating point guide
that's also titled "Why don’t my numbers add up?"
It is working properly, the only problem in this case is in logic of:
echo decode(1.1710299640683E-305);
You can't use "rounded" and "human readable" output of echo function to decode the original value (because you are loosing precision of this double then).
If you will save the return of encode(10000000000000) to the variable and then try to decode it again it will works properly (you can use echo on 10000000000000 without loosing precision).
Please see the example below which you can execute on PHP compiler as well:
<?php
function encode($int) {
$int = round($int);
$left = 0xffffffff00000000;
$right = 0x00000000ffffffff;
$l = ($int & $left) >>32;
$r = $int & $right;
return unpack('d', pack('NN', $l, $r))[1];
}
function decode($float) {
$set = unpack('N2', pack('d', $float));
return $set[1] << 32 | $set[2];
}
echo decode(encode(10000000000000)); // untouched
echo '<br /><br />';
$encoded = encode(10000000000000);
echo $encoded; // LOOSING PRECISION!
echo ' - "human readable" version of encoded int<br /><br />';
echo decode($encoded); // STILL WORKS - HAPPY DAYS!
?>
If you have a reliable fixed decimal point, like in my case and the case of currency, you can multiply your float by some power of 10 (ex. 100 for dollars).
function encode($float) {
return (int) $float * pow(10, 2);
}
function decode($str) {
return bcdiv($str, pow(10, 2), 2);
}
However, this doesn't work for huge numbers and doesn't officially solve the problem.
Seems like it's impossible to convert from an integer to a float string and back without losing the original integer value in php 5.4

PHP: Convert hex color from color input to PHP hex number

I want to convert my hex color from a color input (example: #FFFFFF) to a PHP hex number format (example: 0xFFFFFF).
i tried to replace the # with 0x by using str_replace but this converted it to a string, I want to keep it a number.
Any solution?
Perhaps this function is what you need?
http://www.php.net/manual/en/function.hexdec.php
"Returns the decimal equivalent of the hexadecimal number represented by the hex_string argument. hexdec() converts a hexadecimal string to a decimal number.
hexdec() will ignore any non-hexadecimal characters it encounters."
Some added info:
dechex() will give you a string containing a hex representation of the number if you need it, but it seems you should be dealing with an integer if it's a number that you need to pass around.
Can you try this, Found a function here
function hex2rgb($hex) {
$hex = str_replace("#", "", $hex);
if(strlen($hex) == 3) {
$r = hexdec(substr($hex,0,1).substr($hex,0,1));
$g = hexdec(substr($hex,1,1).substr($hex,1,1));
$b = hexdec(substr($hex,2,1).substr($hex,2,1));
} else {
$r = hexdec(substr($hex,0,2));
$g = hexdec(substr($hex,2,2));
$b = hexdec(substr($hex,4,2));
}
$rgb = array($r, $g, $b);
return implode("", $rgb); // returns the rgb values separated by commas
//return $rgb; // returns an array with the rgb values
}
echo $rgb = hex2rgb("#cc0");

Convert a string containing a number in scientific notation to a double in PHP

I need help converting a string that contains a number in scientific notation to a double.
Example strings:
"1.8281e-009"
"2.3562e-007"
"0.911348"
I was thinking about just breaking the number into the number on the left and the exponent and than just do the math to generate the number; but is there a better/standard way to do this?
PHP is typeless dynamically typed, meaning it has to parse values to determine their types (recent versions of PHP have type declarations).
In your case, you may simply perform a numerical operation to force PHP to consider the values as numbers (and it understands the scientific notation x.yE-z).
Try for instance
foreach (array("1.8281e-009","2.3562e-007","0.911348") as $a)
{
echo "String $a: Number: " . ($a + 1) . "\n";
}
just adding 1 (you could also subtract zero) will make the strings become numbers, with the right amount of decimals.
Result:
String 1.8281e-009: Number: 1.0000000018281
String 2.3562e-007: Number: 1.00000023562
String 0.911348: Number: 1.911348
You might also cast the result using (float)
$real = (float) "3.141592e-007";
$f = (float) "1.8281e-009";
var_dump($f); // float(1.8281E-9)
Following line of code can help you to display bigint value,
$token= sprintf("%.0f",$scienticNotationNum );
refer with this link.
$float = sprintf('%f', $scientific_notation);
$integer = sprintf('%d', $scientific_notation);
if ($float == $integer)
{
// this is a whole number, so remove all decimals
$output = $integer;
}
else
{
// remove trailing zeroes from the decimal portion
$output = rtrim($float,'0');
$output = rtrim($output,'.');
}
I found a post that used number_format to convert the value from a float scientific notation number to a non-scientific notation number:
Example from the post:
$big_integer = 1202400000;
$formatted_int = number_format($big_integer, 0, '.', '');
echo $formatted_int; //outputs 1202400000 as expected
Use number_format() and rtrim() functions together. Eg
//eg $sciNotation = 2.3649E-8
$number = number_format($sciNotation, 10); //Use $dec_point large enough
echo rtrim($number, '0'); //Remove trailing zeros
I created a function, with more functions (pun not intended)
function decimalNotation($num){
$parts = explode('E', $num);
if(count($parts) != 2){
return $num;
}
$exp = abs(end($parts)) + 3;
$decimal = number_format($num, $exp);
$decimal = rtrim($decimal, '0');
return rtrim($decimal, '.');
}
function decimal_notation($float) {
$parts = explode('E', $float);
if(count($parts) === 2){
$exp = abs(end($parts)) + strlen($parts[0]);
$decimal = number_format($float, $exp);
return rtrim($decimal, '.0');
}
else{
return $float;
}
}
work with 0.000077240388
I tried the +1,-1,/1 solution but that was not sufficient without rounding the number afterwards using round($a,4) or similar

Categories