改进算法执行时间和素数

时间:2015-03-24 01:42:31

标签: ruby algorithm primes

我试图找到一个大数字的最大素数值,但它需要太长时间。例如,要找到999999999的最大质数,大约需要55秒。我怎样才能改善这个?

require 'prime'

def highestprime num

  i = 1
  counter = 0
  count = -1
  factors = []
  primes = []

  while (i < num/2) #checks for all factors of number
    i += 1
    if (num%i == 0)
      factors.push(i) #adds all factors to the end factors array
    end
  end

  while (counter != factors.length) #goes through whole array
    counter += 1
    count += 1
    if (factors[count].prime?)
      primes.push factors[count]
    else
      next
    end
  end
  puts primes.pop
end

2 个答案:

答案 0 :(得分:3)

这是我第一眼看到的:

while (i < num/2)

您只需要转到数字的平方根即可计算出所有因素。伪代码类似于:

factors = []
i = 1
while i * i <= num:
    if num % i == 0:
        factors.push(i)
        factors.push(num/i)
    i++

(假设您仍然希望这样做 - 见下文)。


然而,完全没有必要存储所有这些因素,然后寻找最高素数。

由于您按升序查找因子,您也可以按降序同时找到它们,使用&#34;技巧&#34;在上面的第二个factors.push()调用中 - 如果inum的因子,则num / i也是如此。

因此,如果素数因子高于平方根,那么你可以使用相同的循环提前退出(因为那些是在降序顺序中找到的,第一个被发现是最高的。)

否则一直走到平方根并获得迄今为止发现的最高值(在这种情况下你需要最后一个,因为你按照升序搜索)。

这个代码就像:

require 'prime'

def highestprime num
    i = 1
    large = -1
    while (i * i <= num)
        if (num % i == 0)
            if ((num / i).prime?)
                return num / i
            end
            if (i.prime?)
                large = i
            end
        end
        i = i + 1
    end
    return large
end

puts highestprime 999999999

在第二个

下的中返回结果333667
pax$ time ruby testprog.rb
333667

real    0m0.160s
user    0m0.031s
sys     0m0.124s

这比原来的55秒解决方案快了约350倍,希望能够为您提供足够快的速度: - )

如果您通过以下方式获取流程启动/关闭成本,则甚至更快

require 'benchmark'
Benchmark.bm do |xyzzy|
    xyzzy.report {highestprime 999999999}
end

给出:

    user     system      total        real
0.000000   0.000000   0.000000 (  0.000316)

答案 1 :(得分:3)

怎么样:

require 'prime'
999999999.prime_division.last.first #=> 333667

require 'benchmark'
Benchmark.bm do |x|
  x.report {999999999.prime_division.last.first}
end
    user     system      total        real
0.000000   0.000000   0.000000 (  0.000088)