php 的 % 是取余运算符,结果符号与被除数一致,非数学模运算;大整数溢出转 float 后 % 行为异常,应改用 fmod() 或 gmp;需恒正余数时可用 modulo($a, $b) = ($a % $b + $b) % $b。

PHP 的 % 是取余,不是数学模运算
PHP 中的 % 运算符严格来说是「取余(remainder)」,它基于截断除法(truncated division),结果符号永远和被除数一致。这不是 bug,而是语言定义——比如 -7 % 3 得 -1,7 % -3 得 1,-7 % -3 得 -1。关键只看左边那个数的正负,和右边除数的符号无关。
为什么大整数取余突然变负数
当整数超出 int 范围(如 32 位系统上超过 2147483647),PHP 会自动转为 float,但 % 仍按整数逻辑截断计算,中间过程溢出或精度丢失,导致结果反常。典型表现:12121212121 % 1000000 返回 -689767 而非预期的 12121。
- 不要依赖
floatval()后再用%——类型转了,运算符没变,照样错 - 改用
fmod():它专为浮点数设计,能正确处理大数余数,返回值符号也符合浮点除法规则 - 若必须用整数逻辑(比如哈希桶索引),先确保操作数在
PHP_INT_MAX范围内,或用 GMP 扩展做高精度整数运算
想要恒正余数?别硬扛,封装一个 modulo()
很多场景(如数组循环、分页偏移、哈希桶映射)要求余数始终 ≥ 0。直接用 % 在负输入下不可靠,得手动归一化。
安全写法是:($a % $b + $b) % $b(仅适用于 $b > 0)。它先把余数拉进 [0, $b) 区间,再二次取模防越界。
- 封装成函数更稳妥:
function modulo($a, $b) { return ($a % $b + $b) % $b; } - 务必提前检查
$b === 0,否则触发Division by zero警告 - 注意:这个公式不解决大整数溢出问题,只修正符号;大数仍需
fmod()或 GMP
Excel 的 MOD() 和 PHP 的 % 本质不同
Excel 的 MOD(n, d) 结果符号恒与除数 d 相同,公式是 n - d * INT(n/d)(INT 向零取整)。而 PHP 的 % 符号只随被除数变。两者连定义都不一样,混用必踩坑。
比如 MOD(-7, 3) 在 Excel 中是 2,PHP 的 -7 % 3 是 -1。如果你从 Excel 公式迁移到 PHP 逻辑,不能直接替换,得重写余数逻辑。
真正容易被忽略的是:符号规则和数据类型其实是耦合问题。你以为只是“负号烦人”,实际可能是整数溢出 + 运算符语义误解双重作用。调试时先 var_dump(gettype($a), $a),确认是不是早就不小心变成了 float。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











