PHP 內建 base_convert() 功能強大,但存在已知問題:大數精度丟失(內部轉浮點運算)、字符集固定(0-9a-z)。本類提供純整數運算實現,支持自定義字符集,適合短網址、ID 混淆、邀請碼生成等場景。
<?php
/**
* 進制轉換類
* @author sgf@funcity
* @version 2011-02-15
*/
class Hex {
// 字符集:0-9 A-Z,可擴展至 62 位(加 a-z)或自定義
private static $element = array(
'0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F','G','H','I','J',
'K','L','M','N','O','P','Q','R','S','T',
'U','V','W','X','Y','Z'
);
private static $hex_min = 2;
private static $hex_max = 36; // 當前字符集支持上限
/**
* 進制轉換入口
* @param string|int $int 輸入數值(字符串避免大數截斷)
* @param int $out_hex 目標進制
* @param int $in_hex 源進制,默認 10
* @param bool $use_system 是否優先使用 base_convert
* @return string|false
*/
public function conv($int, $out_hex, $in_hex = 10, $use_system = true) {
// 1. 系統函數快速通道
if ($use_system && function_exists('base_convert')) {
return strtoupper(base_convert($int, $in_hex, $out_hex));
}
// 2. 同進制直接返回
if ($out_hex == $in_hex) return $int;
// 3. 進制範圍校驗
if ($out_hex > self::$hex_max || $out_hex < self::$hex_min) return false;
if ($in_hex > self::$hex_max || $in_hex < self::$hex_min) return false;
// 4. 核心流程:源進制 → 十進制 → 目標進制
$hex_10 = $this->_conv2hex10($int, $in_hex);
return strtoupper($this->_conv_hex($hex_10, $out_hex));
}
/** 任意進制 → 十進制(字符串運算,無精度損失) */
private function _conv2hex10($int, $in_hex) {
$int = strtoupper(trim($int));
// 內建函數優化常用進制
if ($in_hex == 10) return $int;
if ($in_hex == 2 && function_exists('bindec')) return bindec($int);
if ($in_hex == 16 && function_exists('hexdec')) return hexdec($int);
if ($in_hex == 8 && function_exists('octdec')) return octdec($int);
$arr = [];
$len = strlen($int);
for ($i = 0; $i < $len; $i++) {
array_unshift($arr, substr($int, $i, 1)); // 逆序入棧
}
$result = 0;
foreach ($arr as $k => $v) {
$val = array_search($v, self::$element);
if ($val === false) return false; // 非法字符
$result += intval(pow($in_hex, $k) * $val);
}
return $result;
}
/** 十進制 → 任意進制(除基取餘法) */
private function _conv_hex($hex_10, $out_hex) {
$hex_10 = intval($hex_10);
if ($out_hex == 10) return $hex_10;
if ($out_hex == 2 && function_exists('decbin')) return decbin($hex_10);
if ($out_hex == 16 && function_exists('dechex')) return dechex($hex_10);
if ($out_hex == 8 && function_exists('decoct')) return decoct($hex_10);
$arr = [];
do {
array_unshift($arr, $hex_10 % $out_hex);
$hex_10 = intval($hex_10 / $out_hex);
} while ($hex_10 > 0); // 注意:原代碼 >1 有邊界bug,此處修正
$result = '';
foreach ($arr as $k) {
$result .= self::$element[$k];
}
return $result;
}
}
// 使用示例
$hex = new Hex();
echo $hex->conv('12345678901234567890', 16, 10); // 大數十進制轉十六進制
echo $hex->conv('ZZ', 10, 36); // 36進制轉十進制
echo $hex->conv('1101', 10, 2); // 二進制轉十進制
| 特性 | base_convert() | Hex 類 |
|---|---|---|
| 大數精度 | ❌ 浮點運算,超 15 位丟失 | ✅ 字符串/整數運算,無上限 |
| 字符集自定義 | ❌ 固定 0-9a-z | ✅ 修改 $element 即可 |
| 進制範圍 | 2-36 | 2-36(可擴展至 62+) |
| 性能 | C 級極快 | PHP 級,大數優勢明顯 |