递归函数的空列表

时间:2013-12-20 09:24:43

标签: haskell tail-recursion

我试图在Project Euler上做一些有趣的工作,但我现在陷入了一个问题,想要继续前进,但似乎无法让我的功能正常工作。我试图计算给定整数的素因子。该功能适用​​于较小的数字,如13195:

> primeFactor 13195
[29,13,7,5]

但是当我运行一个更大的数字,如600851475143:

> primeFactor 601851475143
[] 

这对我来说似乎很奇怪。我知道haskell是一种懒惰的语言,但我不认为它应该是懒惰的......

primeFactor' :: Int -> [Int]
primeFactor' n = [ p | p <- primes' [] [2 .. n], n `mod` p == 0 ]
   where primes' :: [Int] -> [Int] -> [Int]
         primes' ys [] = ys
         primes' ys (x:xs) | x `notMultipleOf` ys = primes' (x:ys) xs
                           | otherwise            = primes' ys xs                                                                                         

-- helper function to primeFactor'
notMultipleOf :: Int -> [Int] -> Bool
notMultipleOf n [] = True
notMultipleOf n xs = and [n `mod` x /= 0 | x <- xs]

3 个答案:

答案 0 :(得分:2)

Int有32位,您无法存储该数字(使用Integer)。

另一方面,您可以使用Data.Numbers.Primes(和see code):

> primeFactors 601851475143
[3,3,23,1009,2881561]
> primeFactors 600851475143
[71,839,1471,6857]

答案 1 :(得分:2)

这是一个整数溢出错误。 Int类型只能代表最高2^31 - 1

的数字
>> maxBound :: Int
2147483647

您输入的号码溢出 -

>> 601851465143 :: Int
556043703

另一方面,如果您使用Integer类型,则没有溢出 -

>> 601851465143 :: Integer
601851465143

答案 2 :(得分:1)

老实说,我不知道你为什么得到一个空名单....或者任何东西。

您正在使用强力方法查找素数列表,将所有数字除以所有较小的素数。这类似于n ^ 2。

这需要多长时间才能完成?

N^2 ~= (601851475143)^2 ~= 10^22 operations

它比这要好一点,因为素数的密度会下降,但不会太多......让我们减去10 ^ 2的因子来解释这个问题。在现代的8核4GHz机器上(假设每个操作1cpu周期....方式乐观),这应该采取

10^20 operations / (10^10 operation/sec) = 10^10 sec ~= 300 years

完成。

您可能想要寻找新算法。