至少在Java中,它不是模数运算符 - 它是余数运算符.
我认为选择这种方式的原因是为了使这种关系起作用(来自JLS):
二进制数字提升(第5.6.2节)后整数操作数的余数运算产生一个结果值,使得(a/b)*b +(a%b)等于a.即使在特殊情况下,这种同一性仍然存在,即被除数是其类型的最大可能量值的负整数,且除数为-1(余数为0).根据这个规则可以得出,只有当被除数为负时,余数运算的结果才是负数,只有当被除数为正时才能为正; 而且,结果的大小总是小于除数的大小.
作为定义的一部分,这种平等关系似乎是合理的.如果你将除法截断为零作为给定,那么就会留下负余数.
来自维基百科(我的重点):
给定两个正数,a(被除数)和n(除数),模n(缩写为mod n)可以被认为是a除以a的余数.例如,表达式"5 mod 4"将评估为1,因为5除以4会留下1的余数,而"9 mod 3"将评估为0,因为9除以3会使余数为0; 在乘以3次3后,没有什么可以从9中减去.(注意,用计算器进行除法不会显示此操作引用的结果,商将表示为小数.)当a或者n是负数,这个天真的定义分解,编程语言在定义这些值方面有所不同.尽管通常在a和n都是整数的情况下执行,但许多计算系统允许其他类型的数字操作数.n的整数模数的范围是0到n-1.(n mod 1总是0; n mod 0未定义,可能导致计算机编程语言中的"除以零"错误)参见模拟算术在数论中应用的较旧和相关的惯例.
我怀疑余数运算符是故意设计成具有那些语义的,我同意这些语义不是很有用。(你有没有写过一个日历程序,在这个纪元之前的日期显示星期日、反星期六、反星期五、...、反星期一?)
相反,负余数是整数除法定义方式的副作用。
A rem B := A - (A div B) * B
Run Code Online (Sandbox Code Playgroud)
如果A div B
定义为trunc(A/B)
,您将获得 C 的%
运算符。如果A div B
定义为floor(A/B)
,您将获得 Python 的%
运算符。其他定义也是可能的。
所以,真正的问题是:
因为这就是 C 的方式。
最初,C 没有指定/
应该如何处理负数。它留给了硬件。
在实践中,每个重要的 C 实现都使用截断除法,因此在 1999 年这些语义正式成为 C 标准的一部分。
因为在无符号除法方面更容易(=更便宜)实现。您只需计算abs(A) div abs(B)
并翻转符号 if (A < 0) xor (B < 0)
。
如果余数不为零,则底除法具有从商中减去 1 的附加步骤。
归档时间: |
|
查看次数: |
720 次 |
最近记录: |