为什么这个天真的素数算法失败了?

时间:2015-04-04 07:28:07

标签: ruby algorithm

我试图在Ruby 2.1中实现this "find the nth prime number" algorithm

我也将它标记为“算法”,因为我认为这个问题与语言无关,并且即使您不熟悉,编写的Ruby代码也很容易阅读。我使用了描述性变量名来帮助它。

  1. 迭代整个数字系统,忽略大于2的数字(2,3,5,7,......)
  2. 对于每个整数p,检查p是否为素数:
    1. 迭代已经找到的小于p
    2. 的平方根的素数
    3. 对于此集合中的每个素数,f,检查它是否是p的因子: 一世。如果f除以p则p为非素数。从下一页继续2。
    4. 如果没有找到因素,则p为素数。继续到3。
  3. 如果p不是我们找到的第n个素数,则将其添加到素数列表中。从下一页继续2。
  4. 否则,p是我们找到的第n个素数,我们应该将它返回。
  5. 听起来很简单。所以我写了我的方法(函数):

        def nth_prime(n)
            primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
    
            primes[-1].upto(Float::INFINITY) do |p|
                return primes[n-1] if primes.length >= n-1
                possible_prime = true
                primes_to_check = primes.select{|x|x<=Math.sqrt(p)}
                primes_to_check.each do |f|
                    if f%p==0
                        possible_prime = false
                        break
                    end
                end
                primes << p if possible_prime
            end
        end
    

    目的是说nth_prime(10)并获得第10个素数。

    解释我的逻辑:

    我从已知素数列表开始,因为算法需要。我列出了前十名。

    然后我遍历整个数字系统。 (primes[-1]+2).upto(Float::Infinity) do |p|将提供从最后一个已知素数加上两个(因为+1将导致偶数和均数超过2不能为素数)的每个数字到无穷大的缩进块p。我没有跳过偶数并且

    如果已知素数列表已经至少 n 元素长,我做的第一件事就是返回 n 质数。这适用于已知值 - 如果你要求第5个,那么你将得到11个结果。

    然后我将标记possible_prime设置为true。这表明没有任何东西证明它是一个素数。我将进行一些测试,如果它没有将标志更改为false,那么p被证明是素数并被附加到已知质数数组。最终该数组将与 n 一样长并返回第n个值。

    我创建了一个数组primes_to_check,其中包含所有已知的素数&lt; = p的平方根。每个人依次以f进行测试。

    如果f可以干净地划分p ,我知道p不是素数,所以我将标志更改为falsebreak,这将我们带出了质数检查循环并返回到无限循环。在该循环中只剩下一个语句,如果标志为真,则附加到known-primes数组的语句,不是这样,我们用下一个数字重新启动循环。

    如果没有f s可以干净地划分p 那么p必须是素数,这意味着它可以存活到素数到检查循环的末尾,并且标志仍然设置为true ,并达到最终'附加p到已知素数'的声明。

    最终,这将使primes数组足够长,以回答“什么是第n个素数?”这个问题。

    问题

    要求获得第10个素数确实得到了29,这是我预先提供的最后一个素数。但要求11获得nil,或没有价值。我已经对代码进行了一百次,并且无法想象没有返回值的情况。

    我做错了什么?

2 个答案:

答案 0 :(得分:1)

return primes[n-1] if primes.length >= n-1

要让primes拥有索引为n-1的元素,其长度必须至少为n

if f%p==0

检查候选人是否可以分割已知素数,而不是候选人是否可被已知素数整除。

primes[-1].upto(Float::INFINITY) do |p|

这将在列表中已经存在的素数处开始循环(29)。正确地发现29是素数,因此它再次被添加到列表中。您希望在29之后以数字开始循环。

答案 1 :(得分:0)

Algorithm for testing prime no.s:
1)Input num
2)counter= n-1
3)repeat 
4)remainder = num%counter
5)if rem=0 then
6)broadcast not a prime.no and stop
7)change counter by -1
8)until counter = 1
9)say its a prime and stop