Conversion from base 10 to base 31 (only works with selected characters)

I would like to convert base 10 numbers to base 31

I would like to use only these characters: 23456789abcdefghjkmnpqrstuvwxyz

As you can see, 5 characters are excluded (I don't need them): 1 0 o l i

Now I have a function, but of course it doesn't work. When 2 is input, outputs 4. Output for tenTo31(2)

must be 2

function tenTo31($num)
{
    $out   = "";
    $alpha = "23456789abcdefghjkmnpqrstuvwxyz";

    while($num > 30)
    {
        $r = $num % 31;
        $num = floor($num / 31) - 1;
        $out = $alpha[$r] . $out;
    }

    return $alpha[$num] . $out;
}

      

Any ideas on how to make this work?

+2


source to share


6 answers


This is a blind guess as to what you want:



$alpha = "yz23456789abcdefghjkmnpqrstuvwx";

      

+4


source


There is a built-in function for converting from one base to another, base_convert () . The alphabet is fixed, but you can use strtr () to replace those numbers with your own.

"The output for tenTo31 (2) must be 2": One possibility is to make "2" the third character again.

function tenTo31($num) {
  static $from = "0123456789abcdefghijklmnopqrstu";
  static $to   = "yz23456789abcdefghjkmnpqrstuvwx";
  return strtr(base_convert($num, 10, 31), $from, $to);
}

for($i=0; $i<31; $i++) {
 echo $i, '=', tenTo31($i), ' | ';
 if ( 9===$i%10 ) echo "\n";
}

      

prints



0=y | 1=z | 2=2 | 3=3 | 4=4 | 5=5 | 6=6 | 7=7 | 8=8 | 9=9 | 
10=a | 11=b | 12=c | 13=d | 14=e | 15=f | 16=g | 17=h | 18=j | 19=k | 
20=m | 21=n | 22=p | 23=q | 24=r | 25=s | 26=t | 27=u | 28=v | 29=w | 
30=x |

      

edit: To convert the base number (31) back to decimal, you first need to reverse the translation (strtr) and then call base_convert (.., 31, 10). You can combine conversion from and to base (31) in one function.

function convert_ten_31($num, $numIsDecimal) {
  static $default = "0123456789abcdefghijklmnopqrstu";
  static $symbols = "yz23456789abcdefghjkmnpqrstuvwx";

  if ( $numIsDecimal ) {
   return strtr(base_convert($num, 10, 31), $default, $symbols);
  }
  else {
   return base_convert(strtr($num, $symbols, $default), 31, 10);
  } 
}

// testing
for($i=0; $i<10000; $i++) {
 $x = convert_ten_31($i, true);
 $x = convert_ten_31($x, false);

 if ( $i!==(int)$x ) {
  var_dump($i, $x);
  die;
 }
}
echo 'done.';

      

It's also easy to write a function like base_convert () that takes characters as parameter and therefore has one flexible function instead of tenTo30 (), tenTo31 (), tenTo32 (), ....

+3


source


You don't use the characters 1 and 0, the first digit in your numbering system is 2 means that 2 is equivalent to 0 in base 10. 3 is equivalent to 1 in base 10 and 4 is equivalent to 2 in base 10.

+2


source


Why are you taking 32 modules? You must use% 31 and / 31. In base 10 we use modules by 10, so we should be in base 31. But if we forget about that, I think your logic is correct. I can't figure out why 2 in base 10 is 4 in base 31 using your "modified digits".

+1


source


While I would advise you to keep working with your learning algorithm, consider using base_convert if you just need to get the job done.

0


source


The mapping according to http://www.crockford.com/wrmg/base32.html looks like this:

function symbolToEncode ($num) {
    $out   = "";
    static $alpha = "0123456789ABCDEFGHJKMNPQRSTVWXYZ*~$=U";

    while ($num >= 37) {
        $r = $num % 37;
        $num = floor ($num / 37);
        $out = $out . $alpha[$r];
    }

    return $out . $alpha[$num];
}

function decodeToEncode ($str) {
  static $from = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*~=$";
  static $to   = "0123456789ABCDEFGH1JK1MN0PQRSTUVWXYZABCDEFGH1JK1MN0PQRSTUVWXYZ*~=$";
  return strtr ($str, $from, $to);
}

      

The real challenge, though, is obviously to write the encodeToSymbol () function. I'm not a PHP expert (my $ in strings probably needs to be avoided somehow - hints?) So I'll leave that to others.

0


source







All Articles