考虑整数除法
a = bq + r
其中a、b、q、r分别是:被除数、除数、商和余数。特别是当 b = 0 时,不存在唯一的 q 满足给定 a 的方程,因此在这种情况下商 q 应该是未定义的。
但是,这种情况下确实存在唯一的r,即r = a。在商和余数总是一起定义的前提下,只要q未定义,r就没有定义,但在编程中,我们经常希望使用余数运算
%
,而不管除法/
。我实际上遇到了我想要的情况if b == 0 then a else a % b end
。
任何编程语言中是否有一个运算符与
%
相同,但当除数为 0 时返回被除数而不是零除错误?
大多数(或所有)编程语言是否有任何原因返回
% 0
的零除错误?
从数学上来说,余数在 0 和 b-1 之间,其中 b 是除数。 因此,当 b = 0 时,r 未定义,因为它必须 >= 0。
有没有一种编程语言可以返还红利?没有把握。我从来没有遇到过。
大多数人不返还股息有什么原因吗? 是的。模数是 CS 中的常见运算,因为它是 CPU 上整数除法的副产品。大多数(如果不是全部)汇编语言都有模数运算,并且该运算使用与除法运算完全相同的硬件。因此,如果你不能在硬件中除以零,那么你就不能在硬件中做模零。
这是否意味着您不能拥有支持此功能的语言?并非如此,但您必须将 if 语句添加到通常是单个指令的操作中。这可能会导致相当严重的性能损失,所以很少(如果有的话)这样做。
我知道定义整数除法余数的三个来源,使其与您的观察结果一致:
Donald Knuth 在 计算机编程艺术,第 1 卷 (1969)(§1.2.4,第 38 页)中将 x mod 0 定义为等于 x。 对于非零除数,它被定义为地板除法的余数: a mod b := a − b × ⌊a ÷ b⌋.
APLK0 手册(也是 1969 年)(第 57 页)定义了一个名为“余数”的运算
|
,定义为 Raymond Boute 的论文 所称的非零除数的“欧几里得除法”的余数,而对于零除数,它返回被除数,但前提是后者非负;否则,这是一个域错误。
“残差”的基本数学定义似乎是
:= inf { x ≥ 0 : ∃ c ∈ ℤ:b|a
− x =a
c }b
对于负
a
和零 b
已经是 inf ∅ = ∞,我认为无法表示。
在 RISC-V 指令集中,“M”扩展(RISC-V 指令集手册,卷 I,版本 20191213,§7.2,第 45 页,表 7.1)定义了返回被除数的余数指令除以零的情况;相应的除法指令返回所有位都设置为 1 的值(有符号除法为 −1,无符号除法为最大可能字值)。
无符号长除法算法的简单实现也将符合 RISC-V 对除法和余数的定义,假设余数可以在目标变量(和所有中间变量)中表示而不会溢出。
为什么以这种方式定义余数不更常见? 我想说这更多地与实际考虑有关,而不是与数学考虑有关。 余数通常被认为是除法的副产品,而不是“环同态本身”;这两个操作通常也使用计算两个结果的通用指令来实现。 由于除以零是未定义的,因此许多体系结构选择它来捕获(触发异常)这种情况,包括流行的 x86。 这意味着余数操作也会陷入困境。 由于多种可能的原因,更高级别的语言很少愿意覆盖此选择:
根本不考虑这个问题,因为合法地出现余数为零的情况很少见,并且乍一看引发异常似乎是一个合理的选择;