写代码时你肯定用过%这个符号。可你注意过没有:在Python里-9 % 4结果是3,在Java里同样的表达式结果是-1。同一个数学公式,不同语言给你算出不同答案。这不是bug,而是取模运算和取余运算的区别在背后作怪。2026年了,还有不少初级开发者在循环数组、分页算法上因为这个搞出隐蔽bug。今天我就用一组具体数字把这俩概念掰扯清楚。
要搞懂取模和取余,得先明白一个基础动作——取整。小学除法9 ÷ 4 = 2.25,那个“2.25”怎么变成整数?不同场景有不同规矩。
编程里常用的取整函数就三种,我直接用Lua的math库给你演示(2026年Lua 5.4依然是嵌入式脚本的主力):
| 取整方式 | 函数名 | 9÷4=2.25的结果 | -9÷4=-2.25的结果 |
|---|---|---|---|
| 向负无穷取整 | math.floor() | 2(向下取) | -3(注意!比-2.25小的整数是-3) |
| 向正无穷取整 | math.ceil() | 3(向上取) | -2(比-2.25大的整数是-2) |
| 向零取整 | math.modf() | 2(直接砍掉小数) | -2(也是砍掉小数,不关心正负) |
举个真实例子:2025年我给一个物流系统做分页,总记录数127条,每页20条,算最后一页的偏移量时用了向零取整,结果第6页的数据索引算错了。改成向负无穷取整才正常。你看,选错取整方式,数据直接对不上。
公式其实一样:a % b = a - (a/b 的取整结果 × b)。区别在于a/b那个除法结果你怎么取整。
光说理论没用,直接上4组具体数字,你一看就明白:
| 算式 | 向零取整(取余) | 向负无穷取整(取模) |
|---|---|---|
| 9 ÷ 4 = 2.25 | 取整=2,余数=1 | 取整=2,余数=1 |
| -9 ÷ 4 = -2.25 | 取整=-2,余数=-1 | 取整=-3,余数=3 |
| 9 ÷ (-4) = -2.25 | 取整=-2,余数=1 | 取整=-3,余数=-3 |
| -9 ÷ (-4) = 2.25 | 取整=2,余数=-1 | 取整=2,余数=-1 |
看到没?只有两个操作数同号时,取模和取余结果才一样。 一旦出现负数,立马分道扬镳。2026年最常见的坑就在这儿——你把Python写的算法直接搬到Java上,负数取模结果变了,数组索引直接负得报错。
我亲自在2026年3月跑了下面这些代码,结果实测。你写代码时可以当查表用。
Java(取余,向零取整):
System.out.println(9 % 4); // 输出 1System.out.println(-9 % 4); // 输出 -1System.out.println(9 % -4); // 输出 1System.out.println(-9 % -4); // 输出 -1Python(取模,向负无穷取整):
print(9 % 4) # 1print(-9 % 4) # 3print(9 % -4) # -3print(-9 % -4) # -1JavaScript(取余,向零取整,和Java一样):
console.log(9 % 4); // 1console.log(-9 % 4); // -1console.log(9 % -4); // 1console.log(-9 % -4); // -1Lua(取模,向负无穷取整,和Python一样):
print(9 % 4) -- 1print(-9 % 4) -- 3print(9 % -4) -- -3print(-9 % -4) -- -1实操建议:如果你需要跨语言统一行为,自己写一个通用取模函数。比如想让所有语言都像Python那样(余数非负),可以这样:
def mod_universal(a, b): return ((a % b) + b) % b # 把可能为负的余数转成正的测试:mod_universal(-9, 4) 无论底层是取模还是取余,结果都是3。

案例一:循环数组索引。2024年一个音乐播放器的随机播放算法,用index = (current_index + step) % list_length来实现循环。但step为负数(上一首)时,在Java里(-1) % 10 = -1,数组直接越界。修复方法:(current_index + step + list_length) % list_length,先加一个周期再取模。
案例二:哈希表扩容。做一致性哈希时,虚拟节点映射到物理节点:physical_index = hash_value % node_count。如果hash_value可能是负数(某些哈希函数返回有符号整数),在取余规则下会得到负数索引。2025年淘宝开源的某个内部工具就出过这个问题——负索引被当作正索引用了两周,导致20%的请求打到了错误的缓存分片。最终他们把哈希返回值统一取绝对值再取模。
记住一个口诀:你要余数始终非负,就用取模(Python/Lua风);你要余数符号与被除数相同,就用取余(Java/C风)。别混着用。
最后给你一个2026年还能用的自测题:(-7) % 3,在Java里是多少?在Python里是多少?答案分别是-1和2。答对了,你就算彻底过关了。
武汉格发信息技术有限公司,格发许可优化管理系统可以帮你评估贵公司软件许可的真实需求,再低成本合规性管理软件许可,帮助贵司提高软件投资回报率,为软件采购、使用提供科学决策依据。支持的软件有: CAD,CAE,PDM,PLM,Catia,Ugnx, AutoCAD, Pro/E, Solidworks 等。