跳到主要内容
CalcMax

取模计算器

范围:-1,000,000,000 – 1,000,000,000

范围:-1,000,000,000 – 1,000,000,000

结果

-47 ≡ 3 (mod 5)

同余式

余数
3

取模是拿一个整数去除另一个整数、只留下它在循环里的位置的那一步:答案永远落在 0 与模数之间,不管两个数是正是负。47 模 5 得 2,而 −47 模 5 得 3,不是 −2。这一处差别就是整页的主题。同一个算式,多数编程语言给 −2,Python 给 3,两边都能自圆其说,因为它们回答的是措辞不同的问题。取模在数学里没有第二种读法:结果不得为负是它定义的一部分。用位置去理解最省事,时钟上 10 点再过 5 小时是 3 点,而 −2 点不是一个位置。模运算里唯一被拒绝的输入是模数 0,因为没有任何数能被 0 整除,模 0 的剩余没有定义。模数本身可以是负数,答案不受影响——5 能整除某个数与 −5 能整除它是同一句话。被除数是 0 时答案是 0,被除数比模数小时答案就是它自己。带余除法里的余数可以跟着被除数的符号,那正是余数计算器那一页讲的事,也是两页分工的地方:同一对整数,两页给出的答案不同,而这不是 bug。页面把同余式与那个数分开印:同余式是主结果。

四种符号组合,以及每一组得到的同余式

被除数模数剩余同余式
-4753-47 ≡ 3 (mod 5)
-121-1 ≡ 1 (mod 2)
475247 ≡ 2 (mod 5)
47-5247 ≡ 2 (mod -5)

第一行与第三行要一起读:被除数一个是 −47、一个是 47,模数都是 5,而剩余分别是 3 与 2。这一对就是整页的主题。按多数计算器与编程语言的口径,第一行会写成 −2,而它写成 3,正是余数与剩余之间的那点差别。再看第一行与第二行:被除数一直是负的,模数从 5 缩到 2,剩余从 3 变成 1——模数减半并不让剩余减半,它是把同一个数放在更短的循环上重新量了一次。第四行的模数是 −5,答案是 2,与模数为 5 的第三行一模一样,符号不敏感在这一处对照里一目了然。四行都可以自己验:被除数减去剩余,结果总是模数的整数倍,而同余式说的就是这件事。

公式

−47 ÷ 5 = −9 余 −2(截断);−2 + 5 = 3,所以 −47 mod 5 = 3,记作 −47 ≡ 3 (mod 5)

a
被除数,也就是被取模的那个数。它可以是负数,而那正是最值得试的一格:a 为负时 a mod n 仍然必须非负,所以 −47 要落在 3 上而不是 −2 上。取 −1000000000 到 1000000000 之间的整数,0 也是一个完全正常的被除数,它的剩余恒为 0
n
模数,也就是拿来除的那个数。它同样可以是负数,而剩余不因它的符号改变:47 mod −5 与 47 mod 5 都是 2,因为「n 整除 a − r」与「−n 整除 a − r」说的是同一句话。唯一被拒绝的取值是 0,另外页面把你敲进去的那个 n 原样印在同余式里,不会悄悄换成它的绝对值
r
剩余,也就是答案本身。它是能从 a 里减掉、并且让剩下的数成为 n 的倍数的最小非负数。两个条件就把它钉死了:r 不小于 0,r 小于 n 的绝对值。−47 mod 5 得 3,因为 3 是让 −47 − 3 = −50 成为 5 的倍数的最小非负数
((a mod n) + |n|) mod |n|
页面实际走的两步,以及第二步为什么在。第一步是多数编程语言算的那一步,它可能交出负数;第二步加上模数的绝对值再取一次模,把结果推进非负区间,而它相对 n 的倍数位置没有变。用 n 的绝对值而不是 n 本身,正是负模数能原样通过的原因
a ≡ r (mod n)
同余式,结果面板的第一行。它说的是 n 整除 a − r,与单独把剩余写出来是同一件事,只是顺带把被除数与模数一起点了名。三横线与 mod 都是记法而不是词,所以它们在站内十个语言下逐字相同,数字之间也不会插入千位分隔符
−47 ≡ 3 (mod 5)
默认输入写全的样子,也是这一页与余数计算器分界的那一格:同样两个数,按四则计算器用的截断口径是 −9 余 −2,这里是 −47 ≡ 3 (mod 5)。把 −47 换成 47 得到的是 2 而不是 3,一个负号让答案沿循环挪了整整一格

凡是答案需要绕回来而不是就此停住的地方都用得上取模。时钟是最老的例子:10 点再过 5 小时是 15 mod 12,也就是 3 点,而剩余不会为负正是让表面读得下去的那一条。日历是同一个形状,一年里的第 100 天、某个日期是星期几,都是模 7 的剩余。编程里取模有四件常做的事:判断整除(a mod n 为 0 就是 n 除得尽)、把一个越界的下标折回范围(环形缓冲区、哈希表)、让计数器在固定区间里循环、以及轮流从列表里取元素。密码学整个架在它上面:RSA 与 Diffie-Hellman 就是大整数上的模运算,而剩余被定义成非负,正是因为带符号的结果没法拿来做后续运算。校验位也是它,从银行卡号到 ISBN,模 9、模 10、模 11 各不相同。当你要问的是「按我手上这台计算器的口径,除进去几次、剩下什么」,余数计算器更合适,因为它把两套口径并排摆出来让你挑;当你要问的是两个数共同的部分是什么,最大公因数那一页直接回答。

算例

  1. 符号的坑:−47 mod 5

    1. 照常做除法并丢掉分数部分:−47 ÷ 5 = −9.4,取整得 −9
    2. −9 × 5 = −45,而 −47 − (−45) = −2,所以截断口径下的余数是 −2
    3. 剩余不得小于 0,于是加上模数的绝对值:−2 + 5 = 3
    4. 检查是否落在区间里:0 ≤ 3 < 5,不用再调整
    5. 读出同余式:−47 ≡ 3 (mod 5),意思是 5 整除 −47 − 3 = −50

    默认输入,也是这一页为什么存在的那一格。四则计算器与多数编程语言对这次除法会报 −9 余 −2;那个答案不算错,它回答的是措辞不同的问题。这里的剩余是 3,因为 3 是让差值成为 5 的倍数的最小非负数。注意 47 mod 5 是 2 而不是 −3 也不是 3——被除数沿循环挪一格,剩余就挪一格,两个剩余恰好差 1 而不是差 5。

  2. 模数为负:47 mod −5

    1. 47 ÷ 5 = 9.4,5 放得进 9 次,9 × 5 = 45
    2. 47 − 45 = 2,已经落在 0 ≤ 2 < 5 里
    3. 模数是负的,但整除不看符号:−5 整除 45,所以它也整除 47 − 2
    4. 同余式按输入原样写:47 ≡ 2 (mod −5)

    这一格说明剩余对模数的符号不敏感。把 −5 换成 5 不会改变答案,因为 −5 整除某个数与 5 整除它是同一件事。页面把负号留在印出来的同余式里,而不是悄悄抹掉;把 −5 改写成 5 会看起来像把你输入的那个符号丢了。对照参考表里模数为 −5 的一行与模数为 5 的一行,能动的只有被除数的符号。

  3. 普通的一格:1234 mod 12

    1. 12 × 100 = 1200,1234 − 1200 = 34,继续:12 × 2 = 24,34 − 24 = 10
    2. 12 × 3 = 36 就超过了 34,所以商是 102、剩下 10
    3. 10 不小于 0 且小于 12,它已经是剩余
    4. 写成同余式:1234 ≡ 10 (mod 12)

    两个正数的平常一格,此时剩余与普通余数一致——把它放进来正是为了说明这一点。两个数都为正时没有什么需要调和,页面做的和任何余数工具一样。有意思的是带负号的那几行。这一对还有第二种读法:1234 mod 12 问的是「钟面有 12 格时,这么长的时间落在哪一格」,而 10 是一个说得通的格,−2 不是。

局限

模数不能是 0。除以 0 没有答案,因此没有余数可报,更没有最小非负的那一个;页面直接拒绝这个输入,而不是回一个看起来像结果的占位数。两个数都必须是整数:小数模数在数学的某些分支里有它自己的定义,但那不是这一页实现的那一个,所以 47.5 会被拒绝,而不是悄悄当成 48 来回答。两个数的绝对值上限都是十亿,这条限制让每一步中间结果都落在双精度还能精确表示整数的范围里;越过它之后算术开始舍入,而答案看起来完全正常却是错的。页面只给剩余与同余式:不印商,不列出与你的被除数同余的其它数,也不做多于一组的模运算。负模数会被接受并按原样印出,这意味着两条说的是同一件事的同余式在页面上可以长得不一样——47 ≡ 2 (mod −5) 与 47 ≡ 2 (mod 5) 是同一句话。最后,下面那张参考表固定在四组数上,不跟着你的输入走;回答你填的那一对的是上面的结果面板。

常见问题

为什么 −47 mod 5 是 3 而不是 −2?
因为剩余被定义为「能从被除数里减掉、并让差值成为模数倍数」的最小非负数。−2 与 3 在这层意义上都合格:−47 − (−2) = −45 与 −47 − 3 = −50 都是 5 的倍数,所以光靠算术分不出该取哪一个。是定义做了选择:剩余住在从 0 到模数之间的那个区间里,而 −2 在区间外。你从编程语言那里拿到什么取决于它选了哪套口径,JavaScript、C、Java、Go 选的是另一套,它们让符号跟着被除数,Python 选的是这一套。两边都没坏,它们回答的是措辞不同的问题。
模数可以是负数吗?
可以,而且剩余不受它的符号影响。负模数能成立是因为整除不看符号:−5 整除某个数当且仅当 5 整除它,所以 −5 的倍数集合与 5 的倍数集合是同一个,那个集合里最小的非负数当然也一样。页面按你输入的样子印模数,不会把 −5 换成 5,因为改写输入看起来像把符号弄丢了。所以 47 mod −5 是 2,47 mod 5 也是 2,两条同余式只差一个负号。
模数填 0 会怎样?
页面会拒绝。模 0 没有值可报:0 只整除 0,所以没有任何 0 的整数倍可以拿来量被除数,也就没有剩余可取。回一个 0、或者回被除数本身,都像是答案而对每一个输入都是错的。拒绝这个输入才是诚实的结果。除以 0 在算术的其它地方同样没有定义,理由是同一个。
这跟站内的余数计算器是同一件事吗?
不是,而同一个算式在两页上给出不同答案,是看清差别最直接的方式。余数计算器把两套口径并排摆出来让你选,因为带余除法在教材里确实有两套,课堂上教哪一套都可能。这一页不给选择,因为取模只有一种读法:答案永远不会是负的。拿 −47 除以 5,余数计算器按默认口径给 −9 余 −2,这一页给同余式 −47 ≡ 3 (mod 5)。想看两套口径在一对具体的数上差多少,去那一页;要的就是剩余本身,留在这一页。
剩余在实际里有什么用?
凡是计数需要绕回来而不能一直涨的地方都用它。钟面是最日常的一例:表盘上十二格,10 点再过 5 小时就是 15 mod 12,也就是 3 点。星期几是同一个道理,模 7。编程里,取模用来判断整除(a mod n 为 0 恰好就是 n 除得尽),用来把越界的下标折回范围(环形缓冲区、哈希表里跑到末尾的下标必须回到开头),也用来让计数器在固定区间里循环。公开密钥密码学是大整数上的模运算,而剩余取非负这条约定在那里格外要紧——会产出带符号结果的算术没法拿来往上搭。
为什么只印同余式,不印商?
因为商不是剩余要说的东西的一部分。同余式点名被除数、剩余与模数,它主张的是模数整除前两者之差。这句话没有商也是完整的:商是「模数整个放得进几次」那个问题的答案,而那个问题属于长除法。要连商一起看,余数计算器与长除法计算器都印它。剩余本身也单独印在结果面板的第二行,只想要那个数的读者不必从句子里把它读出来。

参考资料

相关计算器