如何生成前 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 <= 100 .drop_while |x| x < 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::TrialDivisionGenerator
或 Prime::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?
返回true
,6.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 个素数?的主要内容,如果未能解决你的问题,请参考以下文章