【问题标题】:Ruby - determine if a number is a primeRuby - 确定一个数字是否是素数
【发布时间】:2010-08-29 10:18:30
【问题描述】:

我正在通过Project Euler 上的问题自学Ruby 编程。 我知道有一个内置函数可以做到这一点,但我避免使用内置函数来帮助我学习。

所以我必须编写一个方法来确定一个数字是否是素数。第一种方法有效,但第二种方法无效。谁能解释一下为什么?

 def is_prime n
  for d in 2..(n - 1)
   if (n % d) == 0
    return false
   end
  end

  true
 end

 def is_prime2 n
  foundDivider = false
   for d in 2..(n - 1)
    foundDivider = ((n % d) == 0) or foundDivider
   end
  not foundDivider
 end

【问题讨论】:

  • 这不是您问题的答案……但是为什么在发现它不是质数之后还要检查所有这些数字?您已经得到了您问题的明确答案。
  • 是的,我意识到了——但我这样做是为了确保我知道布尔运算符在 Ruby 中是如何工作的
  • 可以使用以下方法开发更有效的算法:不要迭代偶数(不仅仅是跳过它们)并将循环减少到原始大小的 5-10%。详情在这里:stackoverflow.com/questions/26792960/…

标签: ruby


【解决方案1】:

这是因为= 的优先级高于or。请参阅下面的Ruby's operator precedence table(从高到低优先级):

[ ] [ ]=
**
! ~ + -
* / %
+ -
>> <<
&
^ |
<= < > >=
<=> == === != =~ !~
&&
||
.. ...
? :
= %= { /= -= += |= &= >>= <<= *= &&= ||= **=
defined?
not
or and
if unless while until
begin/end

有问题的行被解析为...

(foundDivider = ((n % d) == 0)) or foundDivider

...这当然不是你的意思。有两种可能的解决方案:

强制优先级成为你真正的意思......

foundDivider = (((n % d) == 0) or foundDivider)

...或改用|| 运算符,其优先级高于=:

foundDivider = ((n % d) == 0) || foundDivider

【讨论】:

  • 这就是我喜欢 StackOverflow 的原因。谢谢一百万
  • 不错。我发现这个问题,答案很有用!我也在通过 Project Euler 来学习 Ruby。我的一项性能改进建议是将范围从 2..(n-1) 更改为 2..(Math.sqrt(n));显着减少迭代次数。
  • 写 foundDivider ||= ((n%d) == 0) 会更好。
【解决方案2】:

Ruby 带有预定义的类,例如 Prime。您所要做的就是将该类添加到您的项目中。

require 'prime'

然后,您可以使用一些 Prime 方法,例如 first 来获取前 x 个主要元素:

Prime.first(5) # Ret => [2, 3, 5, 6, 11]

或者你可以这样做:

Prime.each(100) do |prime|
  p prime # Ret => [2, 3, 5, 7, 11, ..., 97]
end

我希望你觉得这很有用。

【讨论】:

    【解决方案3】:
    def prime(n)
      return false if n < 2
    
      (2..n/2).none?{|i| n % i == 0}
    end
    

    素数是除自身和 1 之外没有正除数的任何数。

    【讨论】:

      【解决方案4】:
      def prime? n
        (2..Math.sqrt(n)).none? {|f| n % f == 0}
      end
      

      因子的范围应该从 2 开始,到 n 的平方根结束,因为每个数字都可以被 1 整除,并且没有任何数字可以被大于其平方根的两个数字整除。

      解释:非质数是两个数的乘积。

      n = f1 * f2
      

      n 总是能被它的平方根整除,所以f1 和f2 都不能大于 n 的平方根,否则f1 * f2 将大于n。因此,至少有一个因子小于或最多等于Math.sqrt(n)。在求素数的情况下,只需要找到一个因数,因此我们应该从2 循环到n 的平方根。

      【讨论】:

        【解决方案5】:

        从循环中查找素数:

        def get_prime_no_upto(number)
          pre = [1]
          start = 2
          primes = (start..number).to_a
          (start..number).each do |no|
            (start..no).each do |num|
              if ( no % num  == 0) && num != no
                primes.delete(no)
                break
              end
            end
          end
          pre + primes
        end
        

        并按如下方式使用:

        puts get_prime_no_upto(100)
        

        干杯!

        【讨论】:

          【解决方案6】:

          以下代码会提示您输入一个数字进行质数检查:

          puts "welcome to prime number check"
          puts "enter number for check: "
            n = gets
            n = n.to_i
          
          def prime(n)
            puts "That's not an integer." unless n.is_a? Integer
            is_prime = true
            for i in 2..n-1
              if n % i == 0
                is_prime = false
              end
            end
            if is_prime
              puts "#{n} is prime!"
            else
              puts "#{n} is not prime."
            end
          end
          
          prime(n)
          

          【讨论】:

            【解决方案7】:

            基于 Darmouse 的回答,但包括极端情况

            def prime? (n)
                if n <= 1
                    false
                elsif n == 2
                    true
                else 
                    (2..n/2).none? { |i| n % i == 0}
                end
            end
            

            【讨论】:

              【解决方案8】:

              仅供参考 - 回复:上面的 DarkMouses prime 方法 - 我发现它真的很有帮助,但有一些错误(我认为!)需要解释:

              它应该是括号而不是方括号...否则你会得到一个 TypeError

              Range can't be coerced into Fixnum (TypeError)
              

              其次,'false' 之前的第一个冒号也会导致错误。据我所知,这是不正确的语法。摆脱它。

              最后,我认为你弄错了?如果你更正了我提到的错误,如果它不是素数,则返回 true,如果是,则返回 false。

              我认为你可以完全放弃三元运算符,然后这样做:

              def prime?(n)
                (2..n/2).none?{|i| n % i == 0} 
              end
              

              显然它没有覆盖边缘情况 (0,1,2),但我们不要分裂头发。

              ...对于那些喜欢分叉的人,这是我对这个问题的完整解决方案:

                  def prime?(n)
                    return false if n < 2
                    (2..Math.sqrt(n)).none? {|num| length % num == 0}
                  end
              

              希望我没有错过任何东西:)

              【讨论】:

                【解决方案9】:

                根据细节,这有点偏离主题,但标题正确:在 ruby​​ 中使用 bash 集成,您可以这样做:

                def is_prime n
                    `factor #{n}`.split.count < 3
                end
                

                bash factor 函数返回一个数字加上他所有的因数,所以如果这个数字是素数,就会有两个字数。

                这仅对代码高尔夫有用。

                【讨论】:

                  【解决方案10】:

                  我试过了,效果很好:

                  def prime?(n)
                    return false if n < 2 
                    return true if n == 3 || n == 2 
                      if (2...n-1).any?{|i| n % i == 0}
                        false
                      else
                        true
                      end
                  end
                  

                  【讨论】:

                    【解决方案11】:
                    def prime?(n)
                      if n <= 1
                      return false
                    
                      else (2..n-1).to_a.all? do |integer|
                       n % integer != 0
                    
                       end
                      end
                    end
                    

                    从我的全盛时期开始?实验室。从消除所有小于或等于 1 的整数开始。

                    【讨论】:

                      【解决方案12】:
                      def prime(n)
                          pn = [2]
                          if n < 2
                             return false
                      
                         else
                      
                           (2..n).each do |i|
                             not_prime = false
                      
                              (2..Math.sqrt(i).ceil).each do |j|
                                 not_prime = true if i % j == 0    
                              end
                             pn.push(i) unless not_prime
                          end
                      
                       end
                      
                      return pn
                      
                      end
                      

                      p prime(30) 给出

                      [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

                      【讨论】:

                        【解决方案13】:

                        如果数字是素数,它将返回true。

                        def prime_number(number)
                          
                            (2..(number-1)).each do |value|   
                                
                                if (number % value) == 0
                                    return false
                                end
                                
                                return true
                            end    
                        end
                        
                        puts prime_number(4)
                        

                        【讨论】:

                          【解决方案14】:

                          ** 对于一个简单的短方法** 首先安装 PRIME GEM

                          require 'prime'
                          `p prime.first(20)`
                          

                          现在将该文件保存为您想要的名称,这将自动生成前 20 个素数!! :-)

                          【讨论】:

                            猜你喜欢
                            • 2016-09-27
                            • 1970-01-01
                            • 2015-01-22
                            • 2013-07-06
                            • 2011-11-27
                            • 2011-06-09
                            • 2011-02-17
                            • 2015-09-15
                            相关资源
                            最近更新 更多