所以我设计了以下的Haskell函数,用于判断给定的数字是否为素数(假设第一个素数为2):
isPrime k = length [ x | x <- [2..k], k `mod` x == 0] == 1
它显然有一个缺陷,即使它可以被多个数字整除,它仍然会继续计算 :(. 是否有任何“明智”的方法,在列表推导中找到多个解决方案时“切断”计算?
此外,您还尝试了哪些其他实现?我在这里不关注性能,只是想看看是否有其他更“Haskell式”的方式来完成相同的事情。
所以我设计了以下的Haskell函数,用于判断给定的数字是否为素数(假设第一个素数为2):
isPrime k = length [ x | x <- [2..k], k `mod` x == 0] == 1
它显然有一个缺陷,即使它可以被多个数字整除,它仍然会继续计算 :(. 是否有任何“明智”的方法,在列表推导中找到多个解决方案时“切断”计算?
此外,您还尝试了哪些其他实现?我在这里不关注性能,只是想看看是否有其他更“Haskell式”的方式来完成相同的事情。
一种快速更改代码的方法是“短路”评估,并依赖于Haskell列表的惰性,即:
isPrime k = if k > 1 then null [ x | x <- [2..k - 1], k `mod` x == 0] else False
k
的第一个因数将导致列表非空,而Haskell实现的null
仅查看列表的第一个元素。
但是,您只需要检查到sqrt(k)
:
isPrime k = if k > 1 then null [ x | x <- [2..isqrt k], k `mod` x == 0] else False
当然,如果您想进行高性能素数测试,最好使用库。
isqrt
更改为sqrt
,这不适用于Integral类型,因此代码会引发错误。第二,您将“relies”更改为“rely”,这破坏了句子的含义(在某种微妙但真实的意义上)。 - Will Nessisqrt
更改为 sqrt
(嘿,学到了新东西,谢谢)是一个错误,而且我在快速打字时错过了单词 rely
,但这些并不是唯一的更改。无论如何,我真的不想再深入探讨了。谢谢。 - Can我很喜欢这种方法:
首先编写一个函数来获取n的所有因数:
factors n = [x | x <- [1..n], mod n x == 0]
然后检查因子是否只有给定的数字和1,如果是,则该数字是质数:
prime n = factors n == [1,n]
虽然这与直接相关的内容有些许不同,但在函数式编程语言中寻找质数方面,我发现Melissa E. O'Neill的《The Genuine Sieve of Eratosthenes》非常有趣。
忽略质数问题,聚焦于更高效的方法来判断 length xs == n
:
hasLength :: Integral count => [a] -> count -> Bool
_ `hasLength` n | n < 0 = False
[] `hasLength` n = n == 0
(_ : xs) `hasLength` n = xs `hasLength` (pred n)
isPrime k = [ x | x <- [2..k], k `mod` x == 0)] `hasLength` 1
这可能有些愚蠢和低效(我是一个完全的Haskell新手),但是在ghci中,函数isMyNumberPrime似乎可以告诉你一个数字是否为质数。
factors n = [x | x <- [2..(n`div` 2)], mod n x == 0]
factormap n = fmap factors $ factors n
isMyNumberPrime n = case factormap n of [] -> True; _ -> False
factors
提供哪些因子?它似乎既不是质因数,也不是所有因子。例如,8
的质因数是[2,2,2]
,而因子是[1, 2, 4, 8]
- 但是你的函数提供了不同的结果。下一个问题是为什么要使用map
- 因子的因子?如果您不介意的话,请让我编辑您的帖子或者请解释得更好一些。谢谢。 - Jörg Brüggmannfactors n = [ n' | n' <- [1..n], n \
mod` n' == 0]` 进行评估。 - Jörg BrüggmannisPrime n = factors n == [1,n]
。 - Jörg Brüggmannfactors n = [x | x <- [2..(n\
div` 2)], mod n x == 0],以及
factormap n = fmap factors $ factors n,
isMyNumberPrime n = case factormap n of [] -> True; _ -> False对于数字
1不起作用。1 不是质数,而
isMyNumberPrime 1的结果却是
True`。 - Jörg Brüggmann