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

PHP 有符號整型轉無符號整型:解決 ID 超過 2^31-1 映射異常

     編輯:PHP 綜合知識

問題場景

短鏈接系統中,自增 ID 與 6 位字符雙向映射。當 ID 超過 2147483647 (2^31-1,32 位有符號整數最大值) 時,PHP 在 32 位系統或舊版本中會將其視為負數,導致映射錯亂:

ID: 2147483647 → ffffVQ → 2147483647  ✓
ID: 2147483648 → nnnnnu → -2147483648 ✗ (溢出為負)
ID: 2147483649 → dnnnnu → -2147483647 ✗

根本原因

  • PHP 整數類型隨平台:32 位系統為有符號 32 位(-2^31 ~ 2^31-1),64 位系統為有符號 64 位(-2^63 ~ 2^63-1)。
  • 32 位環境下,超過 PHP_INT_MAX 的整數會轉為浮點數,精度可能丟失;某些運算(如位運算、格式化)會按有符號 32 位截斷。

解決方案

方法一:sprintf('%u') + float 強制轉換(推薦)

$id = 2147483648; // 超過 2^31-1

// 核心代碼
$unsigned = (float) sprintf('%u', $id);

var_dump($unsigned); // float(2147483648)

%u 格式化為無符號十進制字符串,(float) 轉為浮點數保持精度(53 位尾數可精確表示 2^53 以內整數)。

方法二:BCMath 高精度數學(任意大整數)

$id = '2147483648'; // 以字符串傳入
$unsigned = bcadd($id, '0'); // 返回字符串 '2147483648'
// 參與運算時用 bcadd/bcmul/bcdiv 等

方法三:GMP 擴展(PHP 5.6+ 推薦)

$id = gmp_init('2147483648');
$unsigned = gmp_strval($id); // '2147483648'
// 運算:gmp_add, gmp_mul, gmp_div_q 等

驗證映射邏輯修正

function idToCode($id) {
    $id = (float) sprintf('%u', $id); // 關鍵修正
    $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $code = '';
    while ($id > 0) {
        $code = $chars[bcmod($id, 62)] . $code;
        $id = bcdiv($id, 62);
    }
    return str_pad($code, 6, '0', STR_PAD_LEFT);
}

function codeToId($code) {
    $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $id = '0';
    for ($i = 0; $i < strlen($code); $i++) {
        $id = bcadd(bcmul($id, 62), strpos($chars, $code[$i]));
    }
    return $id; // 返回字符串形式大整數
}

// 測試
$id = '2147483648';
$code = idToCode($id);
$back = codeToId($code);
echo "ID: $id → Code: $code → Back: $back\n"; // 完全一致

最佳實踐建議

  1. 統一使用字符串存儲大 ID:資料庫用 BIGINT UNSIGNED,PHP 端以字符串/BCMath/GMP 處理,避免整型溢出。
  2. 64 位環境部署:現代服務器均為 64 位,PHP_INT_MAX = 9223372036854775807,基本無溢出風險。
  3. ID 生成策略優化:採用雪花算法、UUID、或分段預分配,避免單表自增 ID 耗盡。

參考資源

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