Arrays ruby-更快的素数间隙搜索
我正在创建一个方法,gap(g,m,n) 所有3个参数都是整数Arrays ruby-更快的素数间隙搜索,arrays,ruby,numbers,primes,Arrays,Ruby,Numbers,Primes,我正在创建一个方法,gap(g,m,n) 所有3个参数都是整数 gap找到m和n之间的前两个连续素数,它们的差值为g 例如,间隙(2,1,10)=>[3,5] 在从m到n的范围内,1..10, 间隔为2的前两个连续素数是[3,5] 如果相反,它是gap(1,1,10)=>[2,3] 如果它是gap(6,1,10)=>nil 该方法的工作原理是迭代从最小素数2到参数平方根的每个数字,检查参数是否可以被该范围内的任何值均匀整除。如果是,则该方法返回false 所有素数的间隔都是2、4,或者是
gap找到m和n之间的前两个连续素数,它们的差值为g 例如,间隙(2,1,10)=>[3,5] 在从m到n的范围内,1..10, 间隔为2的前两个连续素数是[3,5] 如果相反,它是gap(1,1,10)=>[2,3] 如果它是gap(6,1,10)=>nil
该方法的工作原理是迭代从最小素数2到参数平方根的每个数字,检查参数是否可以被该范围内的任何值均匀整除。如果是,则该方法返回false
所有素数的间隔都是2、4,或者是由2和4相加而成的数。唯一的例外是2-3的差距 因此,如果给定的间隔参数g是一个类似于3的数字,它既是奇数又大于1,那么该方法会自动返回nil,因为不存在这样的素数间隔
问题 我的问题是这个方法太慢了。通过使用上面的replit链接,您可以获得大约20秒的时间。显然,有可能把它缩短到1秒左右 我尝试过通过过滤掉m..n中已有的偶数进行优化,这很有帮助。但我只是不知道如何才能让这一切进行得更快 我的想法是,在找出m..n中的每一个素数之前,我应该检查每次迭代的间隔是否正确,所以一旦我找到了间隔,我就可以终止该方法,而不看不必要的素数,但我不确定如何实现它
感谢您的帮助,欢迎对我的代码提出任何一般性批评。请使用Jordan的建议回答:
def gap(g, m, n)
if g.odd? && g > 1
return nil
end
recent = 0
current = 0
(m..n).each do |num|
if num.odd? && prime?(num)
current = num
if current - recent == g
break
else
recent = current
end
end
end
[recent, current] unless current - recent != g
end
gap(2, 10000000, 11000000)
#=> [10000139, 10000141]
在3毫秒内完成
谢谢 使用Jordan的建议回答:
def gap(g, m, n)
if g.odd? && g > 1
return nil
end
recent = 0
current = 0
(m..n).each do |num|
if num.odd? && prime?(num)
current = num
if current - recent == g
break
else
recent = current
end
end
end
[recent, current] unless current - recent != g
end
gap(2, 10000000, 11000000)
#=> [10000139, 10000141]
在3毫秒内完成
谢谢 您是否尝试分析您的代码?如果不先分析就很难进行优化,但我敢打赌你应该使用一些更快的方法来寻找素数,也许是筛选埃拉托什尼?我不太确定如何完全分析,但我知道代码的瓶颈是这部分素数=(m..n)。选择{num | num.odd?&&prime?(num)}我认为你的想法(“我想的是…”)这将是一个显著的加速。想想如果你是在纸上写出来的,你会怎么做。你可能会在某个地方写下最近的素数和当前的素数,并在进入下一个素数之前检查间隙。你只需要一个循环就可以了。你试过分析你的代码吗?如果不先分析就很难进行优化,但我敢打赌你应该使用一些更快的方法来寻找素数,也许是筛选埃拉托什尼?我不太确定如何完全分析,但我知道代码的瓶颈是这部分素数=(m..n)。选择{num | num.odd?&&prime?(num)}我认为你的想法(“我想的是…”)这将是一个显著的加速。想想如果你是在纸上写出来的,你会怎么做。你可能会在某个地方写下最近的素数和当前的素数,并在进入下一个素数之前检查间隙。你只需要一个循环就可以了。
def gap(g, m, n)
if g.odd? && g > 1
return nil
end
recent = 0
current = 0
(m..n).each do |num|
if num.odd? && prime?(num)
current = num
if current - recent == g
break
else
recent = current
end
end
end
[recent, current] unless current - recent != g
end
gap(2, 10000000, 11000000)
#=> [10000139, 10000141]