如何生成前 n 个素数?

Posted

技术标签:

【中文标题】如何生成前 n 个素数?【英文标题】:How do I generate the first n prime numbers? 【发布时间】:2012-07-25 07:34:05 【问题描述】:

我正在学习 Ruby 并做一些数学方面的工作。我想做的一件事是生成素数。

我想生成前十个素数,并且只生成前十个。我可以毫无问题地测试一个数字以查看它是否为质数,但想知道生成这些数字的最佳方法是什么?

我正在使用以下方法来确定数字是否为素数:

class Integer < Numeric
  def is_prime?
    return false if self <= 1
    2.upto(Math.sqrt(self).to_i) do |x|
      return false if self%x == 0
    end
    true
  end
end

【问题讨论】:

可以使用以下方法开发更有效的算法:不要迭代偶数(不仅仅是跳过它们)并将循环减少到原始大小的 5-10%。详情在这里:***.com/questions/26792960/… 【参考方案1】:

在 Ruby 1.9 中有一个 Prime 类,您可以使用它来生成素数,或测试一个数字是否为素数:

require 'prime'

Prime.take(10) #=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
Prime.take_while |p| p < 10  #=> [2, 3, 5, 7]
Prime.prime?(19) #=> true

Prime 实现了 each 方法并包含 Enumerable 模块,因此您可以执行各种有趣的事情,例如过滤、映射等。

【讨论】:

这很酷。不知道 Ruby 有一流的课程。知道如何在不使用 Prime 课程的情况下做到这一点吗?也为此欢呼。 要在不使用 Prime 类的情况下实现它,我可能会使用下面答案中描述的埃拉托色尼筛算法。 到底有没有在特定范围内取素数?例如从 [50, 100]? @LưuVĩnhPhúc 当然,试试Prime.take_while |x| x &lt;= 100 .drop_while |x| x &lt; 50 @LưuVĩnhPhúc 这不会仍然计算不需要的素数吗?【参考方案2】:
require 'prime'

Prime.first(10) # => [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

【讨论】:

【参考方案3】:

如果你想自己做,那么这样的事情可以工作:

class Integer < Numeric
    def is_prime?
        return false if self <= 1
        2.upto(Math.sqrt(self).to_i) do |x|
            return false if self%x == 0
        end 
        true
    end 

    def next_prime
        n = self+1
        n = n + 1 until n.is_prime?
        n   
    end 
end

现在获取前 10 个素数:

e = Enumerator.new do |y|
    n = 2
    loop do
        y << n
        n = n.next_prime
    end
end

primes = e.take 10

【讨论】:

我想知道 sqrt 的原因,我在这里找到了回复:studyalgorithms.com/misc/…【参考方案4】:

查看埃拉托色尼筛。这不是 Ruby 特有的,但它是一种生成素数的算法。这个算法背后的想法是你有一个数字列表/数组说

2..1000

你抓住第一个数字 2。遍历列表并消除所有能被 2 整除的东西。你将得到除 2 本身之外不能被 2 整除的所有东西(例如 [2,3,5,7 ,9,11...999]

转到下一个数字 3。再次,消除所有可以除以 3 的内容。继续前进,直到到达最后一个数字,您将得到一系列素数。希望对您有所帮助。

http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

【讨论】:

你如何找到“所有能被 2 整除的东西”(或 3,或其他)? “消除”是什么意思?你是什​​么意思“到达最后一个数字”?不正确的答案将取消算法作为 Eratosthenes 的筛子的资格。 WP 文章试图更仔细地制定它。 你会发现 Sieve 比上面的蛮力方法快得多,而且用 Ruby 编写代码也不难。【参考方案5】:

人们已经提到了Prime 类,这肯定是要走的路。有人还向您展示了如何使用Enumerator,我想使用Fiber 贡献一个版本(它使用您的Integer#is_prime? 方法):

primes = Fiber.new do
  Fiber.yield 2
  value = 3
  loop do
    Fiber.yield value if value.is_prime?
    value += 2
  end
end

10.times  p primes.resume 

【讨论】:

【参考方案6】:

Ruby:打印 N 个素数 http://mishra-vishal.blogspot.in/2013/07/include-math-def-printnprimenumbernoofp.html

include Math

def print_n_prime_number(no_of_primes=nil)

  no_of_primes = 100 if no_of_primes.nil?

  puts "1 \n2"

  count = 1

  number = 3

  while count < no_of_primes

sq_rt_of_num = Math.sqrt(number)

number_divisible_by = 2

while number_divisible_by <= sq_rt_of_num

  break if(number % number_divisible_by == 0)

  number_divisible_by = number_divisible_by + 1

end

if number_divisible_by > sq_rt_of_num

  puts number

  count = count+1

end

number = number + 2

  end

end

print_n_prime_number

【讨论】:

【参考方案7】:

实施了埃拉托色尼筛法(或多或少)

def primes(size)
    arr=(0..size).to_a
    arr[0]=nil
    arr[1]=nil
    max=size
    (size/2+1).times do |n|
        if(arr[n]!=nil) then
            cnt=2*n
            while cnt <= max do
                arr[cnt]=nil
                cnt+=n
            end
        end
    end
    arr.compact!
end

此外,这是我非常喜欢的单线

def primes_c a
    p=[];(2..a).each|n| p.any?|l|n%l==0?nil:p.push(n);p
end

当然,它们会在第一个 n 数字中找到素数,而不是第一个 n 素数,但我认为适应不需要太多努力。

【讨论】:

【参考方案8】:

与问题本身完全无关,但仅供参考:

如果有人不想一次又一次地生成素数(又名贪婪的资源节约者) 或者您可能已经知道必须以某种方式处理后续素数 其他不为人知的奇葩案例

试试这个 sn-p:

  require 'prime'

  for p in Prime::Generator23.new
    # `p` brings subsequent prime numbers until the end of the days (or until your computer explodes)
    # so here put your fabulous code
    break if #.. I don't know, I suppose in some moment it should stop the loop
  end
  fp

如果需要,您还可以使用其他更复杂的生成器,例如 Prime::TrialDivisionGeneratorPrime::EratosthenesGenerator。 More info

【讨论】:

【参考方案9】:
# First 10 Prime Numbers

number = 2
count = 1
while count < 10
  j = 2
  while j <= number
    break if number%j == 0
    j += 1
  end
  if j == number
    puts number 
    count += 1
  end
  number += 1
end

【讨论】:

为什么是负号?请运行代码并查看答案。我现在又检查了一遍。【参考方案10】:

这是一种无需使用 Prime 或数学即可从头开始生成直至“最大”参数的素数的方法。让我知道你的想法。

def prime_test max
    primes = []
    (1..max).each |num| 
        if
            (2..num-1).all? |denom| num%denom >0
        then
            primes.push(num)
        end
    
    puts primes
end

prime_test #enter max

【讨论】:

很好,但根据定义(素数(或素数)是大于 1 的自然数,除了 1 和自身之外没有正除数。大于 1 的自然数不是素数称为合数。)1 不是素数,所以 (2..max) 是完美的。 如果你使用 primes.all 会更好吗?相反(它只会检查 num 是否可以除以素数 - 程序会运行得更快)【参考方案11】:

我认为对于非常大的最大数字来说,这可能是一个昂贵的解决方案,但在其他方面似乎效果很好:

def multiples array
  target = array.shift 
  array.map|item| item if target % item == 0.compact
end

def prime? number
  reversed_range_array = *(2..number).reverse_each
  multiples_of_number = multiples(reversed_range_array)
  multiples_of_number.size == 0 ? true : false
end

def primes_in_range max_number
  range_array = *(2..max_number)
  range_array.map|number| number if prime?(number).compact
end

【讨论】:

【参考方案12】:
class Numeric
  def prime?
    return self == 2 if self % 2 == 0

    (3..Math.sqrt(self)).step(2) do |x|
      return false if self % x == 0
    end

    true
  end
end

有了这个,现在3.prime? 返回true6.prime? 返回false

无需努力实现筛算法,只需验证直到平方根的可除性并跳过奇数,仍然可以快速节省时间。然后,遍历数字,检查素数。

记住:人类时间>机器时间。

【讨论】:

我认为你的意思是跳过偶数。 已修复,很抱歉造成混淆【参考方案13】:
def get_prime(number)
  (2..number).each do |no|
      if (2..no-1).all? |num| no % num  > 0
        puts no
      end
  end
end

get_prime(100)

【讨论】:

欢迎来到 SO。不幸的是,这个问题还有 12 个其他答案。您的答案是否添加了他们没有添加的内容?另外,请确保格式化您的答案,以便我们可以阅读代码。【参考方案14】:

我为编码 kata 这样做并使用了埃拉托色尼筛。

puts "Up to which number should I look for prime numbers?"
number = $stdin.gets.chomp
n = number.to_i
array = (1..n).to_a

  i = 0

while array[i]**2 < n

i = i + 1
array = array.select do |element|
  element % array[i] != 0 || element / array[i] == 1


end
end

 puts array.drop(1)

【讨论】:

【参考方案15】:

这是一个超级紧凑的方法,它用一行代码生成一个素数数组。

  def get_prime(up_to)
    (2..up_to).select  |num| (2...num).all?  |div| (num % div).positive?  
  end

【讨论】:

以上是关于如何生成前 n 个素数?的主要内容,如果未能解决你的问题,请参考以下文章

素数序列的生成及其应用(采用了自研的高效算法)

求前n个素数(C++)

C语言 设计并实现一种大素数随机生成方法; 实现一种快速判定任意一个大数是不是是素数方法 跪求啊

睡前数学一小时之线性筛素数:

列表中的素数

4 列表中的素数