10

基数 2 から基数 62 まで機能する関数が必要base_convert()ですが、使用する必要がある数学がありません。PHP の制限により、bcmath を使用する必要があることはわかっています。これで問題ありません。

これらのような関数は、基数 10 から別の基数 62 までの間で数値を変換しますが、同じ機能を実装したいと思いますbase_convert()。たとえば、任意の基数間で変換できる関数は 1 つだけです。

これを行うと思われる関数を見つけましたが、冗長で遅いコードがあるように感じます。ドイツ語を知っていれば、少し調整したいと思います。=(

関数のより読みやすいバージョンを次に示します。

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;
}

上記の関数を説明したり、任意のベース間の直接変換のプロセスについて説明したりできますか?

4

6 に答える 6

15

PHP 5.3.2以降、bc_mathとgmpの両方が最大62のベースをサポートするようになったため、次のことができます。

echo gmp_strval(gmp_init($mynumber, $srcbase), $destbase);

または同等のbc_math。

于 2011-08-10T16:17:36.207 に答える
9

どこから入手したのか聞かないでください。ウェブで見つけたいくつかの例に基づいていることを覚えています...

  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;
  }
于 2011-01-12T12:10:02.557 に答える
1

数値ベースから人間の言語まで、あらゆる翻訳の問題に対する最も簡単なアプローチは、中間形式を介して翻訳することです。

function bc_base_convert($num, $from, $to) {
    return bc_convert_to(bc_parse_num($num, $from), $to);
}

これで、書く必要があるのはbc_convert_toとだけbc_parse_numです。プラットフォームが数値型を区別する場合は、これを考慮する必要があります。また、浮動小数点数は特別な考慮が必要です。なぜなら、数値はある基数では有限表現を持つかもしれませんが、別の基数ではそうではないからです (たとえば、1/3 は 0.1 3ですが 0.333... 10であり、1/ 10 10は .0001100110011... 2です)。 )。

変換がどのように機能するかについての一般的な説明として、位置ベース システムがどのように機能するかを考えてみましょう。"a n a n-1 ...a 1 a 0 "という形式の数値で基数bは、"a n *b n + a n-1 *b n-1 + ... + a 1 *b 1 + a 0 *b 0 ". 変換は基本的に、別の基底 β のコンテキストで式を評価することによって機能します。

于 2009-12-21T03:42:57.657 に答える
1

私がインターネットで見つけた例とこの回答のほとんどは、BC Math 関数を使用しています。BC Math 関数を使用したくない場合は、次のライブラリを参照してください: http://www.lalit.org/lab/base62-php-convert-number-to-base-62-for-short -urls/

  • BC Math 関数を使用しないため、BC Math ライブラリを使用しなくても動作します。
  • ベースが 36 未満の場合は、実行を高速化するためにネイティブの base_convert 関数を使用します。
  • 出力数値は、ネイティブの base_convert 関数と下位互換性があります。
  • 2 ~ 64 の任意の基数との変換に使用できます。
于 2011-12-08T11:49:42.877 に答える
0

10 進/バイナリ変換に BCMath 関数を使用する方法については、http: //www.exploringbinary.com/base-conversion-in-php-using-bcmath/を参照してください。そのコードを簡単に変更して、別のベースに変換できます。

たとえば、整数を変換する場合は、ルーチン dec2bin_i() および bin2dec_i() を変更します。それらの名前を変更し、基本パラメーターを追加します- dec2base_i($base,$decimal_i) および base2dec_i($base,$num_i) のようなもの、ハードコードされた '2' を変数 $base に変更し、数値の剰余を次の文字との間で変換します変数の名前を変更します。

ここで、任意の基数を変換するには、10 進数を中間として使用し、これらの新しい関数を両方とも呼び出します。たとえば、$dec = base2dec_i('42','123') の後に $b59 = dec2base_i(59,$dec) を呼び出して、基数 42 の数値 "123" を基数 59 に変換します。

(1 回の呼び出しでそれを行う複合関数を作成することもできます。)

于 2009-12-21T14:29:43.873 に答える