我有以下操作:
Prelude> mod (3 - 12) 7
结果我得到了5.
为什么结果为5?
当我尝试这样的事情时:
Prelude> mod -9 7
然后我有错误:
<interactive>:6:1: error:
• Non type-variable argument
in the constraint: Num (t -> a -> a -> a)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a t.
(Num (t -> a -> a -> a), Num (a -> a -> a), Num t, Integral a) =>
a -> a -> a
为什么?
我忘了提一下,我刚开始学习哈斯克尔。
答案 0 :(得分:7)
整数模数,满足
(x `div` y)*y + (x `mod` y) == x
和div
为
整数除法被截断为负无穷大
在您的情况下,x
为-9
而y
为7
。
-9 / 7是-1.2857 ......,(向下舍入)是-2。因此(-9) `div` 7
为-2
。
查看上面的等式,我们得到((-9) `div` 7)*7 + ((-9) `mod` 7) == (-9)
,后者变为(-2)*7 + ((-9) `mod` 7) == (-9)
,后者又简化为(-14) + ((-9) `mod` 7) == (-9)
,(-9) `mod` 7 == (-9) - (-14)
,最后是(-9) `mod` 7 == 5
(因为-9 + 14是5)。
至于你的第二个问题:Haskell将mod -9 7
解析为mod - (9 7)
,即取mod
函数并从中减去将9
应用于7
的结果}。这没有任何意义,因为9
不是一个函数(所以你不能应用它)而且mod
不是一个数字(所以你不能从中减去)。 1
修复是使用mod (-9) 7
强制-
被解析为一元运算符(否定9
)而不是二进制中缀运算符。
1 正如错误消息提示,实际上有一种方法可以让ghc吞下这段代码。它涉及定义Num
的有趣实例,但我不会在这里进行讨论。
答案 1 :(得分:2)
首先,正如评论中已经指出的那样,如果你在没有括号的情况下编写-9
,它将被解释为一个函数,而不是一个负数。
现在mod
部分: modulo (mod :: Integral i => i -> i -> i
)和余数(rem :: Integral i => i -> i -> i
)之间存在差异:
mod :: Integral i => i -> i -> i
整数模数,满足
(x `div` y)*y + (x `mod` y) == x
rem :: Integral i => i -> i -> i
整数余数,满足:
(x `quot` y)*y + (x `rem` y) == x
因此,如果分子和分母都是正数,则没有区别,因为quot
(除法被截断为零)和div
(浮动除法)是等价的。
但是,当分子为负数时,mod
仍为正数,因为div
已被覆盖,而此((div x y)*y
)将会更低或等于实际结果。而rem
将是否定的。
另一方面,如果分母为负数,则结果mod
将为负数,而对于rem
,结果将再次取决于符号的符号分子。
因此mod
始终采用分母的符号,而rem
则取决于分子的符号。
答案 2 :(得分:1)
我猜你期待-2。模数的数学定义是自然数(&gt; = 0),因此它必须返回5(-2 +7)而不是-5。
如果你想要一个返回-2的函数(就像大多数语言一样)你可以使用rem
函数(余数)