我正在创建一个函数来分解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]
我的问题是,为什么会发生这种情况?
答案 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
是乘法的标识,这使得它在没有任何乘法时成为“默认”值。