【发布时间】:2013-09-25 21:32:45
【问题描述】:
我想知道从编程语言/编译器实现的角度来看,使用向负无穷大(Haskell,Ruby)截断而不是向零截断(C,PHP)有哪些好处。
似乎向负无穷大截断是正确的方法,但我还没有找到可靠的来源来支持这种说法,也没有找到这样的决定如何影响编译器的实现。我对可能的编译器优化特别感兴趣,但并不完全是。
相关来源:
【问题讨论】:
标签: haskell compiler-construction truncate
我想知道从编程语言/编译器实现的角度来看,使用向负无穷大(Haskell,Ruby)截断而不是向零截断(C,PHP)有哪些好处。
似乎向负无穷大截断是正确的方法,但我还没有找到可靠的来源来支持这种说法,也没有找到这样的决定如何影响编译器的实现。我对可能的编译器优化特别感兴趣,但并不完全是。
相关来源:
【问题讨论】:
标签: haskell compiler-construction truncate
这些实际上甚至不是唯一的选择,事实上,通常甚至可能不是最好的。我可以在这里总结一下,但最好只链接到这篇出色的论文,该论文对比了截断、下限和欧几里得除法,涵盖了理论和一些实际应用,The Euclidean Definition of Functions div and mod, Raymond T. Boute。
【讨论】:
div 和 mod 是相同的)。差异仅适用于负除数。
这里引用了 ISO/IEC 10967-1:2012 语言独立算术 (vl. LIA-1) C.5.1.2.2 附录 C 中的(信息性)基本原理。省略号...由我插入。
... 常用的舍入规则有两种:向负无穷大舍入 (quotI),以及向负无穷大舍入零。后者在 LIA-1 中未指定,因为当参数具有不同符号时,容易误用。例如,
quotI(-3,2) = -2 向负无穷舍入,在 LIA-1 中指定
divtI(-3,2) = -1 向零舍入,不再由 LIA 的任何部分指定
quotI ... 以及 ... 都满足一个广泛有用的翻译不变量:
quotI(x + i * y, y) = quotI em>( x, y) + i 如果 y ≠ 0,则不会发生溢出
... quotI 是许多数学家首选的整数除法形式。 divtI(LIA不再指定)是Fortran引入的除法形式。
整数除法经常用于分组。例如,如果要将一系列索引项划分为 n 个项的组,则将项
i放入组i/n是很自然的。如果 quotI 用于整数除法,这很好用。但是,如果使用 divtI(LIA 中不再指定),并且i可以为负数,则第 0 组将得到 2 ⋅ n-1 项而不是所需的n。负面i的这种不均匀行为可能会导致细微的程序错误,并且是反对使用 divtI 的强烈理由 ...
【讨论】:
(a+b+c+1)/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 架构,都包含一个整数除法指令,该指令向零舍入。因此,在大多数计算机上计算它可能更有效。我不确定是否有整数除法指令向负无穷大舍入。
【讨论】:
5 % (-3) = 1的地方我想你的意思是5 % (-3) = -1(在python中测试)