首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 自定義進制轉換實現:任意字元集對應十進制雙向轉換

     編輯:PHP 綜合知識

PHP 內建支援 2/8/10/16 進制轉換,但業務常需自定義字元集進制 (如短網址 Base62、避免混淆字元的 Base58、自定義 30/92 進制)。本文實現通用 xbin() 函式,支援任意長度字元集作為「數字符號」,完成十進制整數與自定義進制字串的雙向轉換。

核心實現:十進制 → 自定義進制

<?php
/**
 * 十進制整數轉自定義進制字串
 * 
 * @param string $charset 字元集 (長度 = 基數),如 '0123456789abcdef'
 * @param int    $num     非負整數
 * @return string 自定義進制表示
 */
function xbin(string $charset, int $num): string {
    if ($num < 0) throw new InvalidArgumentException('僅支援非負整數');
    
    $base = strlen($charset);
    if ($base < 2) throw new InvalidArgumentException('字元集至少需 2 個字元');
    
    // 特殊情況:0
    if ($num === 0) return $charset[0];
    
    $result = '';
    while ($num > 0) {
        $remainder = $num % $base;
        $result = $charset[$remainder] . $result; // 前置拼接
        $num = (int)($num / $base);
    }
    
    return $result;
}
?>

反向轉換:自定義進制 → 十進制

/**
 * 自定義進制字串轉十進制整數
 * 
 * @param string $charset 字元集 (需與編碼時一致)
 * @param string $str     自定義進制字串
 * @return int 十進制整數
 */
function xbinDecode(string $charset, string $str): int {
    $base = strlen($charset);
    // 建立字元 → 數值映射表 (O(1) 查找)
    $map = array_flip(str_split($charset));
    
    $result = 0;
    $len = strlen($str);
    
    for ($i = 0; $i < $len; $i++) {
        $char = $str[$i];
        if (!isset($map[$char])) {
            throw new InvalidArgumentException("字元 '{$char}' 不在字元集中");
        }
        $result = $result * $base + $map[$char];
    }
    
    return $result;
}

測試驗證

<?php
// 1. 八進制 (驗證內建 decoct)
$oct = '01234567';
assert(xbin($oct, 9) === '11');
assert(xbinDecode($oct, '11') === 9);
assert(decoct(9) === '11');

// 2. 十六進制 (驗證內建 dechex)
$hex = '0123456789abcdef';
assert(xbin($hex, 31) === '1f');
assert(xbinDecode($hex, '1f') === 31);
assert(dechex(31) === '1f');

// 3. 自定義 30 進制 (0-9 + a-t)
$base30 = '0123456789abcdefghijklmnopqrst';
assert(xbin($base30, 59) === '1t');  // 1*30 + 29 = 59
assert(xbinDecode($base30, '1t') === 59);

// 4. 自定義 92 進制 (可列印 ASCII 排除空白)
$base92 = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`~!@#$%^&*()-=[];\',./{}:"><>?|';
assert(xbin($base92, 183) === '1|'); // 1*92 + 91 = 183
assert(xbinDecode($base92, '1|') === 183);

// 5. 短網址常用 Base62 (避免 0/O, 1/l 混淆可用 Base58)
$base62 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$short = xbin($base62, 123456789); // '8M0k'
assert(xbinDecode($base62, $short) === 123456789);

echo "所有測試通過!\n";
?>

進階:支援負數與浮點數

function xbinFull(string $charset, float $num, int $precision = 6): string {
    $sign = $num < 0 ? '-' : '';
    $num = abs($num);
    
    $intPart = (int)$num;
    $fracPart = $num - $intPart;
    
    $intStr = xbin($charset, $intPart);
    
    if ($fracPart > 0) {
        $fracStr = '.';
        for ($i = 0; $i < $precision; $i++) {
            $fracPart *= strlen($charset);
            $digit = (int)$fracPart;
            $fracStr .= $charset[$digit];
            $fracPart -= $digit;
            if ($fracPart === 0) break;
        }
        return $sign . $intStr . $fracStr;
    }
    
    return $sign . $intStr;
}

應用場景與字元集推薦

場景推薦字元集基數特點
短網址 / ID 混淆Base62: 0-9A-Za-z62大小寫敏感,URL 安全
用戶可讀代碼 (避免混淆)Base58: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz58移除 0/O, I/l, 1/I
大小寫不敏感系統Base32: A-Z2-7 (RFC 4648)32不區分大小寫,人工閱讀友善
極短 ID (含特殊字元)Base92: 可列印 ASCII92最短長度,需 URL 編碼
數學驗證 / 教學自定義任意字元N展示進制本質

PHP 內建進制函式速查

// 進制 → 十進制
bindec('1010')   // 10
octdec('12')     // 10
hexdec('a')      // 10
base_convert('1010', 2, 16) // 'a' (任意基數 2-36)

// 十進制 → 進制
decbin(10)       // '1010'
decoct(10)       // '12'
dechex(10)       // 'a'
base_convert(10, 10, 2)   // '1010'

效能與限制

  • 時間複雜度:O(logbase N),極快
  • PHP 整數上限:PHP_INT_MAX (64位系統 9.22×10¹⁸)
  • 超大整數需用 bcmath 或 gmp 擴充
  • 字元集建議預先建立映射表 array_flip(str_split($charset)) 避免重複計算

自定義進制轉換是短網址、邀請碼、分散式 ID 生成的核心技術,掌握通用實現能靈活應對各種業務編碼需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved