【问题标题】:Trying to create an array with N first primes numbers尝试创建具有 N 个第一个素数的数组
【发布时间】:2020-10-15 08:05:36
【问题描述】:

我对编程很陌生,我正在尝试创建一个方法来返回一个包含 N 个第一个素数的数组。我知道 ruby​​ 中有一个 Prime 类,但我需要创建一个没有它的方法。

这是我到目前为止得到的,但我不断得到奇怪的结果。我觉得有一个简单的逻辑问题,但我找不到它(我不知道 break 在 ruby​​ 中是如何工作的)。

注意事项:

  • 我将我的第一次迭代限制在 2000 年以更快地运行测试。

  • @num 是我必须放入 array_prime 的素数数

  • 我放 2,因为它是唯一的偶素数,所以我可以在第二个循环中执行 2

    def find_prime_array
      array_prime = [2]
      while array_prime.size <= @num
        isPrime = true
        (1..2000).each do |i|
          (3..(i-1)).step(2) do |j| 
            if i % j == 0
              isPrime = false
              break
            end
          end
          array_prime << i if isPrime
        end
      end
      array_prime
    end
    

提前感谢您的帮助。

【问题讨论】:

    标签: arrays ruby primes break


    【解决方案1】:

    这是我的尝试(我不知道 ruby​​...):

    def find_prime_array
      array_prime = [2]
      candidate = 3
      while array_prime.size <= @num
        isPrime = true
        index = 0
        while index<array_prime.size AND array_prime[index] <= squareRoot(candidate) AND isPrime
          if candidate % array_prime[index] == 0
            isPrime = false
            break
          end
          index += 1
        end
        array_prime << candidate if isPrime
        candidate += 2
      end
      array_prime
    end
    

    这个想法是检查候选是否可以被找到的素数整除,检查大于平方根的除数是多余的。
    增加 2 的工作做得很好,因为增加 1 会浪费时间!

    【讨论】:

    • 这里是前 100 个素数:[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61、67、71、73、79、83、89、97、101、103、107、109、113、127、131、137、139、149、151、157、163、167、173、179、181、 191、193、197、199、211、223、227、229、233、239、241、251、257、263、269、271、277、281、283、293、307、311、313、317、331、 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487、491、499、503、509、521、523、541]
    【解决方案2】:

    您似乎正在尝试实现 Sieve of Eratosthenes,修改为返回一定数量的素数而不是检查一定数量的候选者,但您的方法存在几个问题。

    您从 2 作为质数开始,但从 1 开始搜索。您将再次得到 1 和 2。您的搜索应该从 3 开始。

    您是正确的,您可以通过一次迭代两个来提高效率,但是您已经从筛子中留下了 2 个,所以仍然存在偶数。你的候选人你的除数都只需要是赔率。

    检查是否匹配了足够多的素数是在最外层循环中,因此它永远不会停止内层循环。

    @num 应作为参数传入。

    清理所有内容,并将内部循环提取为函数以简化事情...

    # Pass in the number of primes to make the function more useful. Default to @num.
    def find_prime_array(num_primes = @num)
      # Start with 2 so we only have to check odd numbers.
      array_prime = [2]
    
      # Step through only the odd numbers.
      (3..2001).step(2) do |i|
        # Extract the prime check into a function.
        array_prime << i if prime?(i)
    
        # Stop when we have enough primes.
        break if array_prime.size >= num_primes
      end
    
      array_prime
    end
    
    def prime?(i)
      # Also only divide by only the odd numbers.
      (3..(i-1)).step(2) do |j| 
        return false if i % j == 0
      end
      
      return true
    end
    

    但我们可以更有效地做到这一点。筛子的力量是你不必将每个候选人除以每个奇数。你只需要除以你到目前为止找到的素数。

    def find_prime_array(num_primes = @num)
      array_prime = [2]
    
      (3..2001).step(2) do |i|
        array_prime << i if prime?(i, array_prime)
    
        break if array_prime.size >= num_primes
      end
    
      array_prime
    end
    
    def prime?(i, array_prime)
      array_prime.each do |j| 
        return false if i % j == 0
      end
      
      return true
    end
    

    最后,我们可以更习惯地做同样的事情,没有人为的限制。

    def find_prime_array(num_primes)
      primes = [2]
    
      (3..).step(2) do |candidate|
        if primes.none? { |prime| candidate % prime == 0 }
          primes << candidate
        end
        break if primes.size >= num_primes
      end
    
      return primes
    end
    

    【讨论】:

    • 请注意,find_prime_array(2000) 执行 200 万次 (!) 模运算。
    • 如果你在任何地方调用模数,你就没有使用埃拉托色尼筛。
    • 这是一个例子:stackoverflow.com/a/432889/6419007
    • @Stefan 我没有说它有效,只是它有效。我保留了算法。
    猜你喜欢
    • 2018-07-02
    • 1970-01-01
    • 2012-04-29
    • 2015-02-18
    • 1970-01-01
    • 1970-01-01
    • 2018-02-25
    • 2022-11-12
    • 1970-01-01
    相关资源
    最近更新 更多