为什么我的素因子化函数会在结果中附加1?

时间:2014-12-19 01:29:06

标签: haskell primes

我正在创建一个函数来分解haskell中的任何给定数字。所以我创造了这个:

primes :: [Integer]
primes = 2:(sieve [3,5..])
    where
        sieve (p:xs) = p : sieve [x |x <- xs, x `mod` ((p+1) `div` 2 ) > 0]


factorize 2 = [2]
factorize x
    | divisible x = w:(factorize (x `div` w))
    | otherwise   = [x]
    where
          divisible :: Integer -> Bool
          divisible y = [x |x <- (2:[3,5..y]), y `mod` x == 0] /= []

          firstfactor :: Integer -> [Integer] -> Integer
          firstfactor a (x:xs)
              | a `ifdiv` x = x
              | otherwise   = firstfactor a xs
          firstfactor a _ = a

          ifdiv x y = mod x y == 0

          w = firstfactor x primes

该功能正常,但在列表的末尾附加1,例如factorize 80会给出此列表:[2,2,2,2,5,1]我的问题是,为什么会发生这种情况?

1 个答案:

答案 0 :(得分:4)

这来自代码的两个部分。首先,factorize 1[1]。其次,由于x始终可以自行整除,因此您的最终调用将始终为w == x,因此递归将为w:(factorize (w `div` w)),始终为w:(factorize 1)

要解决这个问题,你可以添加一个额外的基础案例来抛弃1的因素:

factorize 1 = []
factorize ...

此外,您可以删除factorize 2 = [2]案例,因为它已被您已有的otherwise案件所包含。

factorize 1 = []在数学上是有道理的,因为1 has no prime factors(记住1本身不是素数!)。这遵循product [] = 1背后的相同逻辑 - 1是乘法的标识,这使得它在没有任何乘法时成为“默认”值。