我想知道从编程语言/编译器实现的角度来看,使用截断对负无穷大(Haskell,Ruby)而不是截断为零(C,PHP)有什么好处。
似乎向负无穷大截断是正确的方法,但我没有找到这种声明的可靠来源,也没有找到这样的决定如何影响编译器的实现。我对可能的编译器优化特别感兴趣,但不仅仅是。
相关来源:
答案 0 :(得分:9)
这些实际上甚至不是唯一的选择,实际上甚至可能不是最好的选择。我可以在这里总结一下,但最好只链接到这篇与truncate,floor和Euclidean部门形成对比的优秀论文,涵盖理论和一些现实世界的应用,The Euclidean Definition of Functions div and mod,Raymond T. Boute。
答案 1 :(得分:4)
以下是ISO / IEC 10967-1:2012 语言无关算术(vl.LIA-1)C.5.1.2.2附录C中(资料性)理由的引用。省略号......由我插入。
...两种舍入规则是常用的:向负无穷大舍入(“ I ),向着零。当争论具有不同的符号时,由于易于使用,因此在LIA-1中没有规定后者。例如,
“ I ( - 3,2)= -2舍入负无穷大,在LIA-1中指定
div t I ( - 3,2)= -1向零舍入,不再由LIA的任何部分指定
quot I ...以及...都满足广泛有用的翻译不变量:
quot I ( x + i * y ,y)= quot I 如果 y ≠0,则em>( x , y )+ i ,并且不会发生溢出
... quot I 是许多数学家首选的整数除法形式。 div t I (不再由LIA指定)是Fortran引入的分割形式。
整数除法经常用于分组。例如,如果要将一系列索引项目划分为 n 项目组,则将项目
i
放入组i/n
是非常自然的。如果 quot I 用于整数除法,则此方法可以正常工作。但是,如果 div t I (不再在LIA中指定),并且i
可以为负数,则组0将获得2⋅ n -1项而不是所需的 n 。负i
的这种不均匀行为可能导致细微的程序错误,并且是反对使用 div t I 的强有力理由。 ..
答案 2 :(得分:3)
在整数除法中有不同类型的舍入有各种权衡。正如杰克麦克阿瑟所说,这不是唯一的。例如,还有四舍五入到最接近的整数。
另一个考虑因素是整数除法和余数是齐头并进的。 quotient * divisor + remainder = dividend
法律成立。因此,不同类型的除法舍入将产生不同类型的余数。例如:
(-5) % 3 = -2
(因为(-5) / 3 = -1
和(-1) * 3 + (-2) = -5
);而5 % (-3) = 2
(因为5 / (-3) = -1
和(-1) * (-3) + 2 = 5
)。(-5) % 3 = 1
(因为(-5) / 3 = -2
和(-2) * 3 + 1 = -5
);而5 % (-3) = 1
(因为5 / (-3) = -2
和(-2) * (-3) + (-1) = 5
)。具有与除数相同符号的余数通常在数学和计算机科学中最有用。通常需要使用固定除数来计算余数。例如,x % 2
。在其余部分具有被除数符号的语言中,如C和Java,此表达式可以计算为-1,0或1,具体取决于x
。但是,在余数具有除数符号的语言中,如Python和Ruby,此表达式只能求值为0(如果为偶数)或1(如果为奇数)。这可能更符合预期。
我相信很多处理器架构,包括x86架构,都包含一个向零舍入的整数除法指令。因此,在大多数计算机上计算它可能更有效。我不确定是否有整数除法的指令向负无穷大方向转。