大多数数学学生和Haskeller都熟悉的Euclidean division theorem表示
给定两个整数a和b,其中b≠0,存在唯一的整数q和r,使得a = bq + r且0≤r<1。 | B |
这给出了商和余数的常规定义。这个1992 paper认为它们是用编程语言实现的最好的。那么,为什么divMod
总是将红利围绕负无穷大?
Exact difference between div and quot表明divMod
已经在quotRem
上做了相当多的额外工作;似乎不太可能更难做到正确。
我根据divMod
中的实现编写了以下欧几里德式GHC.Base
的实现。我很确定它是对的。
divModInt2 :: Int -> Int -> (Int, Int)
divModInt2 (I# x) (I# y) = case (x `divModInt2#` y) of
divModInt2# :: Int# -> Int# -> (# Int#, Int# #)
x# `divModInt2#` y#
| (x# <# 0#) = case (x# +# 1#) `quotRemInt#` y# of
(# q, r #) -> if y# <# 0#
then (# q +# 1#, r -# y# -# 1# #)
else (# q -# 1#, r +# y# -# 1# #)
| otherwise = x# `quotRemInt#` y#
这不仅会产生令人愉快的欧几里德结果,而且它实际上比GHC代码更简单 。它显然最多执行两次比较(而不是GHC代码的四次比较)。
事实上,如果没有太多关于原始人的工作而不是我的工作,这可能完全没有分支。
无分支版本的要点(可能是知道更多的人可以提高效率)。
x `divMod` y = (q + yNeg, r - yNeg * y - xNeg)
where
(q,r) = (x + xNeg) `quotRem` y
xNeg = fromEnum (x < 0)
yNeg = xNeg*(2 * fromEnum (y < 0) - 1)
答案 0 :(得分:0)
此时,我说后向兼容性。 (请参阅@augustss评论。)也许可以在报告的下一个主要版本中进行更改,但您必须说服haskell-prime委员会和可能的GHC开发人员。