converting a number base 10 to base 62 (a-zA-Z0-9)

后端 未结 10 1610
挽巷
挽巷 2020-11-29 01:22

I have a number in base 10. Is there anyway to translate it to a base 62?

Example:

echo convert(12324324);
// returns Yg3 (fantasy example here)


        
相关标签:
10条回答
  • 2020-11-29 01:58

    http://us3.php.net/manual/en/function.base-convert.php#52450

    <?php
    // Decimal > Custom
    function dec2any( $num, $base=62, $index=false ) {
        if (! $base ) {
            $base = strlen( $index );
        } else if (! $index ) {
            $index = substr( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ,0 ,$base );
        }
        $out = "";
    
    
        // this fix partially breaks when $num=0, but fixes the $num=238328 bug
        // also seems to break (adds a leading zero) at $num=226981 through $num=238327 *shrug*
        // for ( $t = floor( log10( $num ) / log10( $base - 1 ) ); $t >= 0; $t-- ) {
    
        // original code:
        for ( $t = floor( log10( $num ) / log10( $base ) ); $t >= 0; $t-- ) {
            $a = floor( $num / pow( $base, $t ) );
            $out = $out . substr( $index, $a, 1 );
            $num = $num - ( $a * pow( $base, $t ) );
        }
        return $out;
    }
    ?>
    

    Parameters:

    $num - your decimal integer

    $base - base to which you wish to convert $num (leave it 0 if you are providing $index or omit if you're using the default (62))

    $index - if you wish to use the default list of digits (0-1a-zA-Z), omit this option, otherwise provide a string (ex.: "zyxwvu")

    <?php
    // Custom > Decimal
    function any2dec( $num, $base=62, $index=false ) {
        if (! $base ) {
            $base = strlen( $index );
        } else if (! $index ) {
            $index = substr( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, $base );
        }
        $out = 0;
        $len = strlen( $num ) - 1;
        for ( $t = 0; $t <= $len; $t++ ) {
            $out = $out + strpos( $index, substr( $num, $t, 1 ) ) * pow( $base, $len - $t );
        }
        return $out;
    }
    ?>
    

    Parameters:

    $num - your custom-based number (string) (ex.: "11011101")

    $base - base with which $num was encoded (leave it 0 if you are providing $index or omit if you're using default (62))

    $index - if you wish to use the default list of digits (0-1a-zA-Z), omit this option, otherwise provide a string (ex.: "abcdef")

    0 讨论(0)
  • 2020-11-29 01:59

    A simpler (and possibly faster) implementation that does not use pow nor log:

    function base62($num) {
      $index = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
      $res = '';
      do {
        $res = $index[$num % 62] . $res;
        $num = intval($num / 62);
      } while ($num);
      return $res;
    }
    
    0 讨论(0)
  • For big numbers, you might want to use the PHP BC library

    function intToAny( $num, $base = null, $index = null ) {
        if ( $num <= 0 ) return '0';
        if ( ! $index )
            $index = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        if ( ! $base )
            $base = strlen( $index );
        else
            $index = substr( $index, 0, $base );
        $res = '';
        while( $num > 0 ) {
            $char = bcmod( $num, $base );
            $res .= substr( $index, $char, 1 );
            $num = bcsub( $num, $char );
            $num = bcdiv( $num, $base );
        }
        return $res;
    }
    
    0 讨论(0)
  • 2020-11-29 02:00

    It was hardly tested and works on real big product. Just copy this functions and use. If needed, you can arrange $baseChars sequentially, I need it for blended.

        /**
         * decToAny converter
         * 
         * @param integer $num
         * @param string $baseChars
         * @param integer $base
         * @return string
         */
        function decToAny($num, $baseChars = '', $base = 62, $index = false) {
    
            $baseChars = empty($baseChars) ? 'HbUlYmGoAd0ScKq6Er5PuZp3OsQCh4RfNMtV8kJiLv9yXeI1aWgFj2zTx7DnBw' : $baseChars;
            if (!$base) {
                $base = strlen($index);
            } else if (!$index) {
                $index = substr($baseChars, 0, $base);
            }
            $out = "";
    
            for ($t = floor(log10($num) / log10($base)); $t >= 0; $t--) {
                $a = floor($num / pow($base, $t));
                $out = $out . substr($index, $a, 1);
                $num = $num - ( $a * pow($base, $t) );
            }
    
            return $out;
        }
    

    Reverse method

        /**
         * anyTodec converter
         * 
         * @param string $num
         * @param string $baseChars
         * @param integer $base
         * @return string
         */
        function anyToDec($num, $baseChars = '', $base = 62, $index = false) {
    
            $baseChars = empty($baseChars) ? 'HbUlYmGoAd0ScKq6Er5PuZp3OsQCh4RfNMtV8kJiLv9yXeI1aWgFj2zTx7DnBw' : $baseChars;
            if (!$base) {
                $base = strlen($index);
            } else if (!$index) {
                $index = substr($baseChars, 0, $base);
            }
            $out = 0;
            $len = strlen($num) - 1;
            for ($t = 0; $t <= $len; $t++) {
                $out = $out + strpos($index, substr($num, $t, 1)) * pow($base, $len - $t);
            }
            return $out;
        }
    
    0 讨论(0)
  • 2020-11-29 02:03
    function convertBase10ToBase62($num){
        $charset="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $endChar=$charset[$num%62];
        $rtn="";
    
        if ( $num == "62" ) { 
            $rtn=$rtn.$charset[1]; 
        } else if ( $num >= 62 ) { 
            $rtn=$rtn.$charset[intval($num/62)%62+1]; 
        }
    
        $num=intval($num/62);
    
        while ($num > 61) {
            if ( is_int($num/62) == true ) { 
                $rtn=$rtn.$charset[0]; 
            } else { 
                $rtn=$rtn.$charset[$num%62]; 
            }
    
            $num=intval($num/62);
        }
        $rtn=$rtn.$endChar;
        echo "\n";
        echo $rtn;
    
        return $rtn;
    }
    
    0 讨论(0)
  • 2020-11-29 02:04

    This function output the same than GNU Multiple Precision if possible…

    <?php
    
    function base_convert_alt($val,$from_base,$to_base){
    static $gmp;
    static $bc;
    static $gmp62;
    if ($from_base<37) $val=strtoupper($val);
    if ($gmp===null) $gmp=function_exists('gmp_init');
    if ($gmp62===null) $gmp62=version_compare(PHP_VERSION,'5.3.2')>=0;
    if ($gmp && ($gmp62 or ($from_base<37 && $to_base<37)))
    return gmp_strval(gmp_init($val,$from_base),$to_base);
    if ($bc===null) $bc=function_exists('bcscale');
    $range='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    if ($from_base==10)
    $base_10=$val;
    else
    {
    $n=strlen(($val="$val"))-++$ratio;
    if ($bc) for($i=$n;$i>-1;($ratio=bcmul($ratio,$from_base)) && $i--)
    $base_10=bcadd($base_10,bcmul(strpos($range,$val[$i]),$ratio));
    else for($i=$n;$i>-1;($ratio*=$from_base) && $i--)
    $base_10+=strpos($range,$val[$i])*$ratio;
    }
    if ($bc)
    do $result.=$range[bcmod($base_10,$to_base)];
    while(($base_10=bcdiv($base_10,$to_base))>=1);
    else
    do $result.=$range[$base_10%$to_base];
    while(($base_10/=$to_base)>=1);
    return strrev($to_base<37?strtolower($result):$result);
    }
    
    
    echo base_convert_alt('2661500360',7,51);
    
    // Output Hello
    
    0 讨论(0)
提交回复
热议问题