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

PHP 大整數取模運算返回負數問題:根因分析與 fmod() 解決方案

     編輯:PHP 綜合知識

問題現象

$res = 16244799483;
echo $res % 9999999; // 輸出 -5069794(預期 4801107)

同樣邏輯在 32 位系統或舊版 PHP 更易觸發。

根本原因

  1. 整數溢位:PHP 整數範圍受平台影響(32 位:±21億,64 位:±9×10¹⁸)。超出範圍時自動轉為 float,但 % 運算子會將操作數轉回整數 運算,導致精度遺失並產生負數。
  2. floatval() 強制轉浮點後,% 仍會轉整數,故無效:
$res = floatval(16244799483);
var_dump($res % 9999999); // 仍輸出 int(-5069794)

正確解法:使用 fmod()

fmod(float $x, float $y) 專為浮點數取模設計,不轉整數。

$res = floatval(16244799483);
echo fmod($res, 9999999); // 輸出 4801107(正確)

封裝通用函數

function safe_mod($dividend, $divisor) {
    return (int) fmod((float) $dividend, (float) $divisor);
}

// 使用
echo safe_mod(16244799483, 9999999); // 4801107
echo safe_mod('16244799483', '9999999'); // 字串也可

補充:PHP 8.0+ 的改進

PHP 8.0 引入 intdiv()(整數除法)並改進大整數處理,但 % 行為未變。跨版本相容仍建議用 fmod()。

效能對比

$n = 1000000;
$start = microtime(true);
for ($i=0; $i<$n; $i++) { $a = 12345678901234 % 9999; }
echo "mod: " . (microtime(true)-$start) . "s\n";

$start = microtime(true);
for ($i=0; $i<$n; $i++) { $a = fmod(12345678901234.0, 9999.0); }
echo "fmod: " . (microtime(true)-$start) . "s\n";

通常 fmod 慢 < 2 倍,可接受。

總結

  • 大整數取模不要用 %。
  • 將被除數轉為 float,改用 fmod()。
  • 若需整數結果,外層包 (int) 或 intval()。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved