views:

538

answers:

2

I need a base_convert() function that works from base 2 up to base 62 but I'm missing the math I need to use, I know that due to the limitations of PHP I need to make use of bcmath, which is fine.

Functions like these convert a number to and from base 10 to another base up to 62, but I want to implement the same functionality of base_convert(), e.g.: a only one function that can convert between arbitrary bases.

I've found a function that seems to do this, but it gives me the feeling of having some redundant and slow code and I would like to tweak it a little bit if I knew German, which I don't. =(

Here is a more readable version of the function:

function bc_base_convert($value, $quellformat, $zielformat)
{
    $vorrat = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    if (min($quellformat, $zielformat) < 2)
    {
     trigger_error('Bad Format min: 2', E_USER_ERROR);
    }

    if (max($quellformat, $zielformat) > strlen($vorrat))
    {
     trigger_error('Bad Format max: ' . strlen($vorrat), E_USER_ERROR);
    }

    $dezi = '0';
    $level = 0;
    $result = '';
    $value = trim(strval($value), "\r\n\t +");
    $vorzeichen = '-' === $value{0} ? '-' : '';
    $value = ltrim($value, "-0");
    $len = strlen($value);

    for ($i = 0; $i < $len; $i++)
    {
     $wert = strpos($vorrat, $value{$len - 1 - $i});

     if (FALSE === $wert)
     {
      trigger_error('Bad Char in input 1', E_USER_ERROR);
     }

     if ($wert >= $quellformat)
     {
      trigger_error('Bad Char in input 2', E_USER_ERROR);
     }

     $dezi = bcadd($dezi, bcmul(bcpow($quellformat, $i), $wert));
    }

    if (10 == $zielformat)
    {
     return $vorzeichen . $dezi; // abkürzung
    }

    while (1 !== bccomp(bcpow($zielformat, $level++), $dezi));

    for ($i = $level - 2; $i >= 0; $i--)
    {
     $factor = bcpow($zielformat, $i);
     $zahl = bcdiv($dezi, $factor, 0);
     $dezi = bcmod($dezi, $factor);
     $result .= $vorrat{$zahl};
    }

    $result = empty($result) ? '0' : $result;

    return $vorzeichen . $result;
}

Can anyone explain me the above function or give me some lights on the process of direct conversion between arbitrary bases?

A: 
outis
I'm sorry but I don't get it, you mean I can't convert lets say from base 61 to base 5 directly?
Alix Axel
You could, but it's easier to use a platform native format as an intermediate form.
outis
A: 

I wrote about using the BCMath functions for decimal/binary conversion here: http://www.exploringbinary.com/base-conversion-in-php-using-bcmath/ . You could easily modify that code to convert to different bases.

For example, in the case of converting integers, modify routines dec2bin_i() and bin2dec_i(). Rename them and add a base parameter -- something like dec2base_i($base,$decimal_i) and base2dec_i($base,$num_i), change the hardcoded '2' to the variable $base, convert the numeric remainders to/from characters of the base, and rename the variables.

Now, to convert between arbitrary bases, use decimal as an intermediate and call both those new functions. For example, convert base 42 number "123" to base 59 by calling $dec = base2dec_i('42','123') followed by $b59 = dec2base_i(59,$dec).

(You could also make a combined function that does it in one call.)

Rick Regan
Note that base_convert() itself -- internally -- uses an intermediate base, as I noted here: http://www.exploringbinary.com/base-conversion-in-php-using-built-in-functions/
Rick Regan