php整型相除余数 php怎么获取两个整数的模【运算】

5次阅读

php的%运算符仅支持整数,浮点数会报错或异常;fmod()可处理浮点但行为不同;大整数应使用bcmod()或gmp_mod()。

php整型相除余数 php怎么获取两个整数的模【运算】

PHP 里 % 运算符只支持整数,浮点数直接报错

PHP 的取模运算符 % 看似简单,但一用就错——它**不接受浮点操作数**。哪怕你传的是 5.0(int)3.9,只要底层类型是 Float,运行时就会抛出 Warning: A non-Integer value encountered(PHP 8.0+)或静默转为 int 导致结果异常(旧版本)。

常见踩坑场景:从表单、json数据库读出来的数字,表面是整数,实际是 String 或 float 类型;或者计算过程中用了 /,结果自动变成 float。

  • 用前先断言:is_int($a) && is_int($b),别信变量名
  • 强制转整:(int)$a % (int)$b 可行,但要注意溢出和负数截断行为(见下条)
  • 更安全的替代:用 fmod() 处理可能含小数的场景(但它返回的是 float 余数,不是整数)

fmod() 返回的是 float 余数,和 % 行为不等价

fmod($a, $b) 能处理 float,但它的数学定义是「满足 $a = $b * floor($a/$b) + fmod($a,$b) 的余数」,这跟整数取模的向零截断逻辑不同。尤其当操作数为负时,结果差异明显:

var_dump(7 % 3);     // int(1) var_dump(fmod(7, 3)); // float(1) <p>var_dump(-7 % 3);     // int(-1) ← 向零截断 var_dump(fmod(-7, 3)); // float(-1)</p><p>var_dump(-7 % -3);    // int(-1) var_dump(fmod(-7, -3)); // float(-1)</p><p>var_dump(7 % -3);     // int(1) var_dump(fmod(7, -3)); // float(1)

看起来一样?再试这个:

立即学习PHP免费学习笔记(深入)”;

var_dump(-8 % 3);     // int(-2) var_dump(fmod(-8, 3)); // float(1)

原因:% 是整数除法余数(truncated division),fmod() 是浮点除法余数(Euclidean 风格变体)。所以别把 fmod() 当作 % 的“升级版”来用。

  • 要严格整数模运算:确保输入是 int,用 %
  • 要兼容 float 输入且需数学上连续的余数:用 fmod(),但得接受返回 float
  • 想统一负数行为(比如总要正余数):自己写 ($a % $b + $b) % $b,但仅限 $b > 0 且 $a, $b 是 int

字符串或 JSON 拿来的“整数”很可能不是 int

HTTP 请求参数、json_decode() 默认结果、mysql fetch_assoc() 的数值字段——这些地方出来的“数字”,PHP 很可能存成 stringfloat。而 % 对 string 会尝试转换,对 float 则直接警告。

典型错误现象:Warning: A non-integer value encountered in ... on line X,但脚本继续执行,余数却是错的(比如 "10" % "3" 得到 1,看似对,但 "10.0" % "3" 就崩了)。

  • 检查类型:gettype($a)is_numeric($a) 更准
  • 稳妥转换:filter_var($a, FILTER_VALIDATE_INT),失败返回 false,比 (int) 强制转换更可控
  • 数据库字段:pdo 中设 PDO::ATTR_EMULATE_PREPARES = false + PDO::ATTR_STRINGIFY_FETCHES = false,可减少自动 string 化

大整数超出 int 范围时,% 会静默溢出

PHP 的 int 有平台限制(32 位系统最大约 21 亿,64 位约 9E18)。如果两个 bigint 字符串(比如 UUID 时间戳、加密 ID)直接强转 (int) 再取模,高位直接丢弃,余数毫无意义。

例如:(int)"9223372036854775808" === 0(在 64 位 PHP 中已超 PHP_INT_MAX),接着 0 % 1000,完全失真。

  • 确认是否真需要整数模:如果是哈希分片、ID 路由,通常可用 bcmod()(bcmath 扩展)处理任意长度数字字符串
  • bcmod("9223372036854775808", "100")"8",安全可靠
  • 没开 bcmath?用 GMP:gmp_strval(gmp_mod("9223372036854775808", "100"))
  • 注意:bcmod() 不支持负数被除数,需自行处理符号

真正麻烦的从来不是语法怎么写,而是你根本没意识到那个“整数”早就不是整数了,或者它大到连 int 都装不下。

text=ZqhQzanResources