作業を行った行とは別にmod' x y | x >= y = (mod' (x-y) y)
、2 つの引数を転置する役割がありました。mod' x y
は「x mod'
y , the remainder on dividing
x by
y」を意味します。
mod' :: Int -> Int -> Int
mod' x 0 = x
mod' 0 x = 0
mod' x y | x >= y = (mod' (x-y) y)
| otherwise = x
ゼロ
div
そしてmod
方程式から来ます
x = (x `div` y) * y + (x `mod` y)
y==0
であるから、 は方程式を機能させるべきである_ * 0
と0
主張することができます。ただし、これは が であるため、非正格を想定しています。Haskell では、は厳密なので、いずれにせよ方程式は崩れます。おそらく、黙って先に進むよりも、ゼロ除算を含む計算を行ったことをユーザーに警告する方がよいでしょう。x `mod` 0
x
*
x `div` y
error "divide by zero"
*
mod' _ 0 = error "division by zero"
とにかく、modは負の数に対してどのように機能するはずですか?
OK、重要なことは、これは剰余であるため、 と 0x `mod` y
の間にあるはずでy
あり、 に等しくないためy
、次のように計算できるということ7 `mod` 3
です。
さて、何かを見るとどうなるmod (-3)
でしょうか?ここで、「~の間y
」とは、剰余が負になることを意味するため、次のように計算できます(-7) `mod` (-3)
。
もちろん、マイナス 3 を取ることは 3 を足すことと同じですが、重要な点は、符号を変えるだけで、同じ計算と答えが得られるということです。
(-x) `mod` (-y) = -(x `mod` y)
x
どちらの場合も、との符号がy
一致しました。それらが異なる場合はどうなりますか?まず、正の値を持つことができますy
:
第二に、負の値を持つことができますy
:
ご覧のとおり、方法は異なりますが、符号規則の変更
(-x) `mod` (-y) = -(x `mod` y)
まだ立っています。
では、関数に何をすべきでしょうか?
ステップ 0: ゼロのチェック ステップ 1: 負のチェックy
. その場合は、符号規則の変更を使用します。
ステップ 2: 陽性を確認しx
ます。もしそうならy
、あなたが下になるまで服用してくださいy
。
ステップ 3: それ以外の場合は、ゼロを超えるまで追加y
します。
コードでは、それは
mod' :: Int -> Int -> Int
mod' x 0 = error "mod by zero"
mod' 0 x = 0
mod' x y | y < 0 = - (mod' (-x) (-y))
| x > 0 = modpos x
| otherwise = modneg x
where
modpos x | x < y = x
| otherwise = modpos (x-y)
modneg x | x >= 0 = x
| otherwise = modneg (x+y)
そして簡単なチェック:
ghci> all id [x `mod` y == x `mod'` y | x <- [-10 .. 10], y<- [-10 .. 10],y/=0]
True
ロジックが正しいことを示しています。