46

haskell レポートから:

y がゼロ以外の場合、quot、rem、div、および mod クラス メソッドは次の法則を満たします。

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

quotはゼロに向かって切り捨てられた整数除算であり、 の結果はdiv 負の無限大に向かって切り捨てられます。

例えば:

Prelude> (-12) `quot` 5
-2
Prelude> (-12) `div` 5
-3

結果がどのように切り捨てられるかの違いが問題になる例は何ですか?

4

3 に答える 3

40

多くの言語には「mod」または「%」演算子があり、除算後に0に向かって切り捨てて余りを与えます。たとえば、C、C ++、Java、そしておそらくC#は、次のように言います。

(-11)/5 = -2
(-11)%5 = -1
5*((-11)/5) + (-11)%5 = 5*(-2) + (-1) = -11.

Haskellは、この動作を模倣することを目的としていますquotremいくつかの不自然な状況では、いくつかのCプログラムの出力との互換性が望ましいかもしれないと想像できます。

Haskelldivmod、そしてそれに続くPythonの/と%は、数学者(少なくとも数論者)の慣習に従って、除算を常に切り捨て(0に向かってではなく-負の無限大に向かって)、余りが常に非負になるようにします。したがって、Pythonでは、

(-11)/5 = -3
(-11)%5 = 4
5*((-11)/5) + (-11)%5 = 5*(-3) + 4 = -11.

Haskellのdiv、そしてmodこの振る舞いに従ってください。

于 2008-12-04T07:52:36.930 に答える
27

これはあなたの質問に対する正確な答えではありませんが、x86 上の GHC では、int 上の quotRem は単一のマシン命令にコンパイルされますが、divMod はかなり多くの作業を行います。したがって、速度が重要なセクションにいて、正の数のみを扱っている場合は、quotRem が最適です。

于 2008-12-04T22:53:20.357 に答える
7

問題になる簡単な例は、整数が偶数か奇数かをテストすることです。

let buggyOdd x = x `rem` 2 == 1
buggyOdd 1 // True
buggyOdd (-1) // False (wrong!)

let odd x = x `mod` 2 == 1
odd 1 // True
odd (-1) // True

もちろん、odd を次のように定義するだけで、これらの問題について考えるのを避けることができることに注意してください。

let odd x = x `rem` 2 /= 0
odd 1 // True
odd (-1) // True

y > 0一般に、 forはx mod y常に何か>= 0x rem y返す一方で、 0 または x と同じ符号の何かを返すことを覚えておいてください。

于 2008-12-04T07:00:36.910 に答える