tags:

views:

595

answers:

4

I have some large HEX values that I want to display as regular numbers, I was using hexdec() to convert to float, and I found a function on php.net to convert that to decimal, but it seems to hit a ceiling, eg: $h = 'D5CE3E462533364B'; $f = hexdec($h); echo $f .' = '. exp_to_dec($f); Output: 1.5406319846274E+19 = 15406319846274000000

Result from calc.exe = 15406319846273791563

Is there another method to convert large hex values? Thanks :)

A: 

Doesn't intval(var, base) take care of it?

From the PHP Manual.

mcandre
var_dump(intval('D5CE3E462533364B', 16)); gets me int 2147483647 ; not really what he expected ^^ ; See the note on the documentation of intval, which says : "The maximum value depends on the system. 32 bit systems have a maximum signed integer range of -2147483648 to 2147483647. So for example on such a system, intval('1000000000000') will return 2147483647."
Pascal MARTIN
+2  A: 

As said on the hexdec manual page :

The function can now convert values that are to big for the platforms integer type, it will return the value as float instead in that case.

If you want to get some kind of big integer (not float), you'll need it stored inside a string... This might be possible using BC Math functions.

For instance, if you look in the comments of the hexdec manual page, you'll find this note

If you adapt that function a bit, to avoid a notice, you'll get :

function bchexdec($hex)
{
    $dec = 0;
    $len = strlen($hex);
    for ($i = 1; $i <= $len; $i++) {
        $dec = bcadd($dec, bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i))));
    }
    return $dec;
}

(This function has be copied from the note I linked to ; and only a bit adapted by me)

And using it on your number :

$h = 'D5CE3E462533364B';
$f = bchexdec($h);
var_dump($f);

The output will be :

string '15406319846273791563' (length=20)

So, not the kind of big float you had ; and seems OK with what you are expecting :

Result from calc.exe = 15406319846273791563


Hope this help ;-)
And, yes, user notes on the PHP documentation are sometimes a real gold mine ;-)

Pascal MARTIN
Thank you muchly. I already had BC Math installed so this got the 'answer' over the GMP solution, but I'm sure both do the job. Thanks :)
aland
You're welcome :-) Have fun!
Pascal MARTIN
A: 

1.5406319846274E+19 is a limited representation of you number. You can have a more complete one by using printf()

printf("%u\n", hexdec($h));

...will output "15406319846273792000". PHP uses floats for such big numbers, so you may lose a bit of precision. If you have to work with arbitrary precision numbers, you may try the bcmath extension. By splitting the hex into two 32-bit words (which should be safe on most systems) you should be able to get more precision. For instance:

$f = bcadd(bcmul(hexdec(substr($h, 0, -8)), 0x100000000), hexdec(substr($h, 8)));

...would set $f to 15406319846273791563.

Josh Davis
+2  A: 

hexdec() switches from int to float when the result is too large to be represented as an int. If you want arbitrarily long values, you're probably going to have to roll your own conversion function to change the hex string to a GMP integer.

function gmp_hexdec($n) {
  $gmp = gmp_init(0);
  $mult = gmp_init(1);
  for ($i=strlen($n)-1;$i>=0;$i--,$mult=gmp_mul($mult, 16)) {
    $gmp = gmp_add($gmp, gmp_mul($mult, hexdec($n[$i])));
  }
  return $gmp;
}

print gmp_strval(gmp_hexdec("D5CE3E462533364B"));

Output: 15406319846273791563
Randy
I would have set this as the answer but I don't have GMP extension installed (although maybe I should).
aland