Question

The example #2 of the PHP manual page of the dechex() function is the following :

// The output below assumes a 32-bit platform.
// Note that the output is the same for all values.
echo dechex(-1)."\n";
echo dechex(PHP_INT_MAX * 2 + 1)."\n";
echo dechex(pow(2, 32) - 1)."\n";

The above example will output:

ffffffff
ffffffff
ffffffff

I am trying to reproduce that behaviour on a x64 system :

echo dechex(-1)."\n";
echo dechex(PHP_INT_MAX * 2 + 1)."\n";
echo dechex(pow(2, 64) - 1)."\n";

I am expecting :

ffffffffffffffff
ffffffffffffffff
ffffffffffffffff

But, I get :

ffffffffffffffff
0
0

Any idea in what's going on here?

Was it helpful?

Solution

First of all it's important to note that PHPs dechex function requires integer input.

On a 64bit system PHP does not have support for 64bit integers.

For example the typical PHP_INT_MAX on a 64 bit system is:

 9223372036854775807

This is also the maximum integer (!) number dechex can accept.

If you pass in pow(2, 64) - 1 it's a float (1.844674407371E+19) which converted to integer is integer 0 hence dechex returns the string "0".

Same applies if you pass in 2^64 as string "18446744073709551615". It is converted to integer and it's integer value is 9223372036854775807 on 64 bit system. So dechex returns the string "7fffffffffffffff".

Therefore if you need to deal with these numbers, you can not use PHP's integer type and therefore dechex is not the right tool for the job. Instead you can use bcmath and the gmp functions to achieve what you're looking for:

echo gmp_strval(bcadd(bcmul(2, PHP_INT_MAX), 1), 16), "\n";
echo gmp_strval(bcsub(bcpow(2, 64), 1), 16), "\n";

OTHER TIPS

I suspect that there is a bug with dechex on a 64 bit platform related to the fact that the largest integer that can be stored as a float is pow(2,53)-1 which is 9007199254740991. The manual does warn about using really large numbers with base_convert because you can be working with floats and strange results can occur b/c of the imprecision of the floating point system. Something similar may be occurring with dechex.

PHP accepts a number as a parameter for dechex which may be either an integer or a float but the floats are in reality just a device for expressing whole numbers that overflow the boundaries of int. The fact is that the code that you ran successfully on a 32 bit platform also passes to dechex a value that exceeds the maximum integer value for a 32 bit platform, passing in a float, as below comments indicate:

<?php

echo "Max int: ",PHP_INT_MAX, "\n"; // Max int: 2147483647
$num = (PHP_INT_MAX * 2) + 1;
var_dump($num);   //                // float(4294967295)
echo dechex($num),"\n";            // ffffffff
echo dechex(-1);                   // ffffffff

You may wish to file a bug report at bugs.php.net.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top