怎么mod计算

时间:2017-02-04 21:39:42

标签: haskell

我有以下操作:

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

为什么?

我忘了提一下,我刚开始学习哈斯克尔。

3 个答案:

答案 0 :(得分:7)

mod is specified

  

整数模数,满足

(x `div` y)*y + (x `mod` y) == x

div

  

整数除法被截断为负无穷大

在您的情况下,x-9y7

-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函数(余数)