Convert Large Integer to Hexadecimal without PHP Math extension

PHP has a couple of functions to convert integers to hexadecimal, dechex() and base_convert(). However, both functions lose precision on large integers.

For example:

$bigint_hash = '11442725345190069619';
$hexadecimal_hash = '9eccba134669c573';
$converted_hash = dechex( $bigint_hash+0 ); //+0 just makes sure a float is passed to function
echo 'Decimal value is: '. $bigint_hash. "/n";
echo 'Hexidecimal value SHOULD be : '. $hexadecimal_hash. "/n";
echo 'Hexidecimal value converts to: '. $converted_hash. "/n";

//outputs
/*
Decimal value is: 11442725345190069619
Hexidecimal value SHOULD be : 9eccba134669c573
Hexidecimal value converts to: 9eccba134669c800
*/

There are PHP solutions that allow you to create an alternative to dechex() / base_convert( $num, 16, 10 ) with more accuracy but they require BC Math or GMP extensions to be installed.

A colleague of mine passed on an alternative to dechex() or base_convert( $num, 16, 10 ) that was apparently listed on php.net but was removed due (I’m guessing!) to some bad language filter despite how semantically accurate the function’s naming convention uses.

Here it is:

/* Follows the syntax of base_convert (http://www.php.net/base_convert)
 * Created by Michael Renner @ http://www.php.net/base_convert 17-May-2006 03:24
 * His comment is has since been deleted. The function will tell you why.
*/
function unfucked_base_convert($numstring, $frombase, $tobase)
{

    $chars = "0123456789abcdefghijklmnopqrstuvwxyz";
    $tostring = substr($chars, 0, $tobase);

    $length = strlen($numstring);
    $result = '';
    for ($i = 0; $i < $length; $i++)
    {
        $number[$i] = strpos($chars, $numstring{$i});
    }
    do
    {
        $divide = 0;
        $newlen = 0;
        for ($i = 0; $i < $length; $i++)
        {
            $divide = $divide * $frombase + $number[$i];
            if ($divide >= $tobase)
            {
                $number[$newlen++] = (int)($divide / $tobase);
                $divide = $divide % $tobase;
            } elseif ($newlen > 0)
            {
                $number[$newlen++] = 0;
            }
        }
        $length = $newlen;
        $result = $tostring{$divide} . $result;
    } while ($newlen != 0);
    return $result;
}

The source can be found on GitHub.

Now I can convert with freedom:

$bigint_hash = '11442725345190069619';
$hexadecimal_hash = '9eccba134669c573';
$converted_hash = unfucked_base_convert( $bigint_hash, 16, 10 );
echo 'Decimal value is: '. $bigint_hash. "/n";
echo 'Hexidecimal value SHOULD be : '. $hexadecimal_hash. "/n";
echo 'Hexidecimal value converts to: '. $converted_hash. "/n";

//outputs
/*
Decimal value is: 11442725345190069619
Hexidecimal value SHOULD be : 9eccba134669c573
Hexidecimal value converts to: 9eccba134669c573
*/

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s