【问题标题】:Get primes below x得到低于 x 的素数
【发布时间】:2012-08-04 00:42:06
【问题描述】:

我正在尝试编写一个返回给定数字以下所有素数列表的过程。

例如:

Prelude>primes 8  
[2,3,5,7]  

当我尝试加载文件时,我得到Parse error in pattern Failed, modules loaded: none. 如果有人能指出我正确的方向,我将不胜感激。

primes :: Int -> [Int]
primes x < 2 = []
primes x | isPrime x == True = primes (x - 1) ++ x
         | otherwise = primes (x - 1)

isPrime :: Int -> Bool
isPrime x | x < 2 = False
          | x == 2 || x == 3 = True
          | divEven x == True = False
          | divOdd x 3 == True = False
          | otherwise = True

divEven :: Int -> Bool
divEven x | mod x 2 == 0 = True
          | otherwise = False

divOdd :: Int Int -> Bool
divOdd x num | mod x num == 0 == True
             | num <= x/2 = divOdd x (num + 2)
             | otherwise = False

【问题讨论】:

  • x == Truex 相同。
  • 谢谢维特斯。实际上我之前没有它,但是在它无法编译时添加了它。我想这并没有什么区别。

标签: haskell primes


【解决方案1】:

这是使用list comprehensions(也称为in Wikipedia)重新编写的函数,也许这在视觉上更明显:

primes :: Int -> [Int]
primes x | x<2  = [] 
         | x<4  = [2..x]
         | True = primes (x-1) ++ [x | isPrime x]

你的isPrime

isPrime x = x > 1 && 
          ( x < 4 || 
            and [ rem x n /= 0 | n <- 2 : [3,5..(div x 2)+2] ] )

and is a function defined in standard Prelude。它将测试列表中的条目,从左到右,查看是否全部为True。它将在遇到第一个 False 条目时停止,因此不会探索其余条目。

有时当代码在视觉上更明显时,更容易看到如何改进它。

【讨论】:

  • 你的 isPrime 每次都会检查 3 个条件,最好有一个无限的素数列表并从中取出 x 个元素
  • @Vixen 这不是“我的”; :) 我只是以不同的形式写下了 OP 代码,这在 IMO 中更清晰,更容易看到如何改进。 :) 你说得对;作为一个独立的功能,它必须检查它们,所以它应该在“primes”内部进行,这样可以删除额外的检查等等。我想为 OP 提供一个简单的起点。
【解决方案2】:

小错误的集合。

  1. 你的语法不正确。

    primes x < 2 = []
    

    你的意思可能是

    primes x | x < 2 = []
    

    同样,你写的地方

    divOdd x num | mod x num == 0 == True
    

    你可能是说

    divOdd x num | mod x num == 0 = True
    
  2. 类型签名

    divOdd :: Int Int -> Bool
    

    无效。你可能是说

    divOdd :: Int -> Int -> Bool
    
  3. xInt 类型,(/) :: Fractional a =&gt; a -&gt; a -&gt; a 不能应用于它。你的意思可能是num &lt;= x `div` 22 * num &lt;= x

    divOdd :: Int Int -> Bool
    divOdd x num | mod x num == 0 == True
                 | num <= x/2 = divOdd x (num + 2)
                 | otherwise = False
    
  4. x 的类型是 Int,而不是 [Int](++) :: [a] -&gt; [a] -&gt; [a] 将不适用于它。

    primes x | isPrime x == True = primes (x - 1) ++ x
    

    也许你的意思

    primes x | isPrime x == True = primes (x - 1) ++ [x]
    

最后,这是一种相当低效的生成素数的方法。你考虑过筛子吗? Prime numbers - HaskellWiki 现在对你来说可能有点困难,但有很多不同的策略。

【讨论】:

  • 非常感谢。这些确实是我的问题。正如您可能已经猜到的那样,我对 Haskell 相当陌生。我去看看筛子,谢谢你的建议。
  • 对于`div`的中缀使用可能需要反引号转义
  • @roldugin Stack Overflow 的 Markdown 使得在内联代码中插入反引号变得很困难——问题和答案的工作方式与 cmets 不同——但我已经修复了它;现在应该是正确的。
  • @ephemient 您可以在答案和问题中的内联代码片段周围放置双反引号,然后单反引号将起作用。
猜你喜欢
  • 1970-01-01
  • 2020-03-30
  • 1970-01-01
  • 1970-01-01
  • 2014-05-09
  • 2015-12-09
  • 1970-01-01
  • 1970-01-01
  • 2021-11-12
相关资源
最近更新 更多