使用截断朝向负无穷大而不是零的优点

时间:2013-09-20 13:12:49

标签: haskell compiler-construction truncate

我想知道从编程语言/编译器实现的角度来看,使用截断对负无穷大(Haskell,Ruby)而不是截断为零(C,PHP)有什么好处。

似乎向负无穷大截断是正确的方法,但我没有找到这种声明的可靠来源,也没有找到这样的决定如何影响编译器的实现。我对可能的编译器优化特别感兴趣,但不仅仅是。

相关来源:

Division in Haskell

When is the difference between quotRem and divMod useful?

3 个答案:

答案 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法律成立。因此,不同类型的除法舍入将产生不同类型的余数。例如:

  • 将舍入舍入为零,产生一个总和与被除数相同的余数。例如,在C和Java中,(-5) % 3 = -2(因为(-5) / 3 = -1(-1) * 3 + (-2) = -5);而5 % (-3) = 2(因为5 / (-3) = -1(-1) * (-3) + 2 = 5)。
  • 向负无穷大舍入舍入,产生一个总和与除数一致的余数。例如,在Python和Ruby中,(-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架构,都包含一个向零舍入的整数除法指令。因此,在大多数计算机上计算它可能更有效。我不确定是否有整数除法的指令向负无穷大方向转。