甚至数量为2的素数分解

时间:2018-01-29 03:28:06

标签: haskell recursion

我正在做一个Haskell练习题,涉及编写一个函数,如果2将偶数次除以参数num,则返回true。例如,如果num为奇数,则返回True,因为2分为0次,0为偶数。 8作为参数返回False,因为2分为3次,3为奇数。 我知道如何使用两个参数来解决这个问题,其中第二个参数是一个计数器,你继续将你的第一个参数除以2直到它等于1,如果计数器mod 2 == 0,则返回True。但是我们应该只使用一个数字作为参数,...所以我该怎么做呢? 我的功能,

isGreen :: Int -> Int -> Bool
isGreen num count
    | (num==1)&&(count `mod` 2 == 0) = True
    | (num==1)&&(count `mod` 2 /= 0) = False
    | otherwise = isGreen (div num 2) (count + 1)

2 个答案:

答案 0 :(得分:2)

您可以使用独占或功能来执行此操作。我不相信这会被纳入Haskell,所以你可以自己制作一个

xor :: Bool -> Bool -> Bool
xor True True = False
xor True False = True
xor False True = True
xor False False = False

isGreen :: Int -> Bool
isGreen num
    | (num < 0) = isGreen (-num)
    | (mod num 2 /= 0) = True
    | num > 1 = xor True (isGreen (div num 2))
    | num == 1 = True

这样做的原因是我们每次爬回调用堆栈时都会在True和False之间翻转。

Example: isGreen 8 =
xor True (isGreen 4) = 
xor True (xor True (isGreen 2) =
xor True (xor True (xor True isGreen 1)) = 
xor True (xor True (xor True True)) = 
xor True (xor True False) = xor True (True) = 
False

答案 1 :(得分:1)

请注意,您的版本没有给出奇数的正确答案:

> isGreen 0 3
False
>

因为它应使用n == 1来检查终止,而应使用odd n

无论如何,作为替代方案,您可以通过观察如果x可被4整除,则构建直接递归定义,则isGreen xisGreen (x `quot` 4)相同。否则,2的可分性将给出答案:

isGreen x | x == 0         = error "zero is neither green nor not green"
          | x `rem` 4 == 0 = isGreen (x `quot` 4)
          | even x         = False  -- one two left over
          | otherwise      = True   -- no twos left over

,并提供:

> map isGreen [1..10]
[True,False,True,True,True,False,True,False,True,False]
>

作为旁注,我已经习惯使用quotrem。至少在英特尔体系结构和使用原始整数类型时,当你不关心结果的符号时,它们比divmod更快,所以我已经习惯了它们的使用在测试可分性时。同样,有些人可能会将第二种情况写成:

| let (q,r) = x `quotRem` 4, r == 0 = isGreen q

理由是单quotRem次来电可以在单独的remquot来电中保存分组。不可否认,这两种优化都非常愚蠢。