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?
As of PHP 5.3.2 both bc_math and gmp now support bases up to 62, so you can just do:
echo gmp_strval(gmp_init($mynumber, $srcbase), $destbase);
or the bc_math equivalent.
Please dont ask me where i got it from, i just remeber that its based of some examples i found on the web...
function charset_base_convert ($numstring, $fromcharset, $tocharset) {
$frombase=strlen($fromcharset);
$tobase=strlen($tocharset);
$chars = $fromcharset;
$tostring = $tocharset;
$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 easiest approach for any translation problems, from numeric base to human languages, is to translate via an intermediate format.
function bc_base_convert($num, $from, $to) {
return bc_convert_to(bc_parse_num($num, $from), $to);
}
Now all you need to write are bc_convert_to
and bc_parse_num
. If the platform distinguishes numeric types, you'll need to take this in to account. Also, floating point numbers require special consideration because a number may have a finite representation in one base, but not another (e.g. 1/3 is 0.13 but 0.333...10, and 1/1010 is .0001100110011...2).
As for a generalized explanation of how conversion works, consider how positional base systems work. A numeral of the form "anan-1...a1a0" in a base b represents the number "an*bn + an-1*bn-1 + ... + a1*b1 + a0*b0". Conversion basically works by evaluating the expression in the context of another base β.
Most of the examples I found on the internet and in this answers use BC Math functions. If you do not want to use use BC Math functions, you can have a look at this library: http://www.lalit.org/lab/base62-php-convert-number-to-base-62-for-short-urls/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With