我很好奇这些语言(
Java,C …),忽略了模数运算的数学定义.
在模块操作中返回负值是什么意思(根据定义,应该返回一个正数)?
解决方法
我怀疑余下的操作符被故意地设计为具有这些语义,我同意不是非常有用. (你会写一个日历程序,显示星期天,反周六,反周五,…,反周一的时间之前的日期?)
相反,负余数是定义整数除法的副作用.
A rem B := A - (A div B) * B
如果A div B定义为trunc(A / B),则可以得到C的%运算符.如果A div B定义为floor(A / B),则可以得到Python的%运算符.其他定义是可能的.
所以真正的问题是:
为什么C,Java,C#等使用截断整数除法?
因为这是C的方式.
为什么C使用截断分割?
最初,C没有指定/应该处理负数.它把它留给了硬件.
在实践中,每个重要的C实现都使用截断划分,所以在1999年,这些语义正式成为C标准的一部分.
为什么硬件使用截断划分?
因为在无符号划分方面实现起来更容易(=更便宜).如果(A <0)xor(B <0),则只计算abs(A)div abs(B)并翻转符号. 如果剩余部分为零,则地板部门将额外的步骤从商中减去1.