【问题标题】:Improving algorithm execution time and prime numbers改善算法执行时间和质数
【发布时间】:2015-05-27 05:32:07
【问题描述】:

我试图找到一个大数的最大素值,但它需要的时间太长了。例如,要找到 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

【问题讨论】:

标签: ruby algorithm primes


【解决方案1】:

这是我要看的第一件事:

while (i < num/2)

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

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

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


但是,绝对没有必要存储所有这些因数然后寻找最高质数。

由于您按升序查找因子,因此您也可以同时按降序查找它们,使用上面第二个 factors.push() 调用中的“技巧” - 如果 i 是 @ 的因子987654325@,然后是num / i

所以你可以使用 same 循环来提前退出,如果素因数高于平方根(因为这些是按 descending 顺序找到的,第一个找到的是最高的)。

否则继续直到达到平方根并获得迄今为止找到的最高值(在这种情况下,您需要最后一个,因为您是按升序搜索的)。

这个代码是这样的:

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 in well

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)

【讨论】:

  • 太棒了!只有一个问题,为什么是long = -1?你只是选择了一个任意值吗?
  • @RubyUser,假设您的意思是 large 而不是 long,是的,我想选择一个通常不能由代码返回的任意值(因为所有被检查的数字都是正数)。换句话说,它是一个哨兵值,意味着没有找到解决方案。
  • 是的,抱歉,我就是这个意思。谢谢。
【解决方案2】:

怎么样:

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)

【讨论】:

  • 哇,我不知道这些方法。
  • 如果读者对@Amadan 的评论感到困惑(现在已经消失了!),让我解释一下。在我发布后几秒钟,他发布了与我完全相同的解决方案。看到我的回答,删了他的。我联系了他,评论了他对另一个问题的回答,建议他恢复他的回答,因为这是平局。他的评论基本上说一个答案就足够了。
猜你喜欢
  • 2011-06-17
  • 2017-06-09
  • 2021-06-12
  • 2021-09-26
  • 1970-01-01
  • 2010-12-16
  • 1970-01-01
  • 2021-06-21
  • 1970-01-01
相关资源
最近更新 更多