理解進制轉換原理有助於處理編碼、哈希、加密等底層邏輯。本文提供通用的「任意進制 → 十進制」轉換函數,支援整數、小數、字母數字混合(如十六進制),並可選擇性輸出計算步驟供教學演示。
<?php
/**
* 任意進制字符串轉十進制數值
*
* @param string $number 來源數字字符串(支援 2-36 進制)
* @param int $base 進制基數 (2-36)
* @param bool $showSteps 是否返回計算步驟
* @return float|array 十進制數值,或 [value, steps] 數組
*/
function baseToDecimal(string $number, int $base, bool $showSteps = false): float|array {
if ($base < 2 || $base > 36) {
throw new InvalidArgumentException("Base must be between 2 and 36");
}
// 分離整數與小數部分
if (str_contains($number, '.')) {
[$integerPart, $fractionPart] = explode('.', $number, 2);
} else {
$integerPart = $number;
$fractionPart = '';
}
$steps = [];
$total = 0.0;
// 1. 整數部分:從右向左(低位到高位)
$integerPart = strrev(strtoupper($integerPart));
for ($pos = 0; $pos < strlen($integerPart); $pos++) {
$char = $integerPart[$pos];
$digitValue = charToValue($char);
if ($digitValue >= $base) {
throw new InvalidArgumentException("Digit '$char' (value $digitValue) invalid for base $base");
}
$power = $base ** $pos;
$contribution = $digitValue * $power;
$total += $contribution;
if ($showSteps) {
$steps[] = [
'position' => $pos,
'digit' => $char,
'digit_value' => $digitValue,
'power' => $power,
'contribution' => $contribution,
'formula' => "$digitValue × $base^$pos = $contribution"
];
}
}
// 2. 小數部分:從左向右(高位到低位,負冪次)
if ($fractionPart !== '') {
$fractionPart = strtoupper($fractionPart);
for ($pos = 1; $pos <= strlen($fractionPart); $pos++) {
$char = $fractionPart[$pos - 1];
$digitValue = charToValue($char);
if ($digitValue >= $base) {
throw new InvalidArgumentException("Digit '$char' invalid for base $base");
}
$power = $base ** -$pos; // 負冪次
$contribution = $digitValue * $power;
$total += $contribution;
if ($showSteps) {
$steps[] = [
'position' => -$pos,
'digit' => $char,
'digit_value' => $digitValue,
'power' => $power,
'contribution' => $contribution,
'formula' => "$digitValue × $base^(-$pos) = $contribution"
];
}
}
}
return $showSteps ? ['value' => $total, 'steps' => $steps] : $total;
}
/**
* 字符轉數值 (0-9, A-Z -> 0-35)
*/
function charToValue(string $char): int {
$char = strtoupper($char);
$ord = ord($char);
if ($ord >= ord('0') && $ord <= ord('9')) return $ord - ord('0');
if ($ord >= ord('A') && $ord <= ord('Z')) return $ord - ord('A') + 10;
throw new InvalidArgumentException("Invalid digit character: $char");
}
/**
* 十進制轉任意進制(補全雙向)
*/
function decimalToBase(float $number, int $base, int $precision = 10): string {
if ($base < 2 || $base > 36) throw new InvalidArgumentException("Base 2-36");
$integerPart = (int)floor($number);
$fractionPart = $number - $integerPart;
// 整數部分
$intStr = '';
if ($integerPart === 0) $intStr = '0';
while ($integerPart > 0) {
$rem = $integerPart % $base;
$intStr = valueToChar($rem) . $intStr;
$integerPart = intdiv($integerPart, $base);
}
// 小數部分
$fracStr = '';
for ($i = 0; $i < $precision && $fractionPart > 0; $i++) {
$fractionPart *= $base;
$digit = (int)floor($fractionPart);
$fracStr .= valueToChar($digit);
$fractionPart -= $digit;
}
return $fracStr ? "$intStr.$fracStr" : $intStr;
}
function valueToChar(int $value): string {
return $value < 10 ? (string)$value : chr(ord('A') + $value - 10);
}
?>
<?php
// 1. 二進制轉十進制
$result = baseToDecimal('1011', 2, true);
echo "1011₂ = {$result['value']}₁₀\n";
foreach ($result['steps'] as $s) {
echo " 位{$s['position']}: {$s['formula']}\n";
}
// 輸出:
// 1011₂ = 11₁₀
// 位0: 1 × 2^0 = 1
// 位1: 1 × 2^1 = 2
// 位2: 0 × 2^2 = 0
// 位3: 1 × 2^3 = 8
// 2. 十六進制轉十進制
echo baseToDecimal('FF', 16); // 255
// 3. 八進制帶小數
$result = baseToDecimal('17.4', 8, true);
echo "17.4₈ = {$result['value']}₁₀\n"; // 15.5
// 4. 36進制(0-9 + A-Z)
echo baseToDecimal('ZZ', 36); // 1295 (35*36 + 35)
// 5. 反向驗證
echo decimalToBase(255, 16); // FF
echo decimalToBase(15.5, 8); // 17.4
?>
| 函數 | 用途 | 限制 |
|---|---|---|
bindec() | 二進制→十進制 | 僅整數,字符串參數 |
octdec() | 八進制→十進制 | 僅整數 |
hexdec() | 十六進制→十進制 | 僅整數,支援大數字 |
base_convert() | 任意進制互轉 (2-36) | 大數字可能丟失精度(浮點運算),不支援小數 |
intval($str, $base) | 字符串按進制解析為整數 | 2-36進制,忽略非法字符,不報錯 |
<?php
// base_convert 大數字精度問題
$bigHex = 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
echo base_convert($bigHex, 16, 10); // 可能科學計數法或不精確
// BCMath 高精度
function bcBaseConvert(string $num, int $fromBase, int $toBase): string {
// 先轉十進制(BCMath 字符串運算)
$dec = '0';
$pow = '1';
$num = strrev(strtoupper($num));
for ($i = 0; $i < strlen($num); $i++) {
$digit = charToValue($num[$i]);
$dec = bcadd($dec, bcmul((string)$digit, $pow));
$pow = bcmul($pow, (string)$fromBase);
}
// 十進制轉目標進制
if ($dec === '0') return '0';
$result = '';
while (bccomp($dec, '0') > 0) {
$rem = bcmod($dec, (string)$toBase);
$result = valueToChar((int)$rem) . $result;
$dec = bcdiv($dec, (string)$toBase, 0);
}
return $result;
}
echo bcBaseConvert($bigHex, 16, 10); // 精確完整輸出
?>
掌握通用進制轉換邏輯,能應對各類非標準編碼場景,也是理解計算機數值表示的基礎功底。