有三种不同的明显方式来定义对负数的整数除法,以及三种相应的方式来定义余数:
- 底除法,其中商向负无穷大下底,余数与除数具有相同的符号。
- 截断除法,其中商向零截断,余数与被除数相同。
- 欧几里得除法,其中商在任何方向上被截断,余数为正。
所有这三个都保留了整数除法的基本定律:
dividend = divisor * quotient + remainder
所以,这三个都不是“正确”或“错误”。*
当然,这并不能阻止人们进行圣战。Knuth 以“数学上正确”为基础,主张使用底除法。Wirth 主张截断除法,因为它“不那么令人惊讶”。Raymond Boute 认为整数除法是根据欧几里得算法定义的。我不会试图通过争论他们三个人(包括该领域最重要的两个人)都是错误的来解决一场长达数十年的圣战……
某些语言通过具有两种不同的功能来解决此问题。**
假设 Python 采用了 Knuth 的定义,所以它的模运算符有除数的符号。
* 当然,选择商和余数的不匹配定义是另一回事。或者,更糟糕的是,指定一个并保留另一个实现定义,就像 C 在 C99 之前所做的那样。
** 这特别有趣,因为他们并不总是一致地知道哪个是哪个。至少当它们被称为rem
and时mod
,rem
是与 一起出现的那个div
,而当它们被称为and或and时,mod
无论是 floored 还是 Euclidean 都不匹配……</p>
div
rem
remainder
mod
modulo