【问题标题】:Determining if a number is prime判断一个数是否为素数
【发布时间】:2011-05-24 09:18:35
【问题描述】:

我已经阅读了很多关于这个主题的代码,但其中大多数产生的数字一直是质数,直到输入数字。但是,我需要只检查给定输入数字是否为素数的代码。

这是我能写的,但它不起作用:

void primenumber(int number)
{
    if(number%2!=0)
      cout<<"Number is prime:"<<endl;
    else 
      cout<<"number is NOt prime"<<endl;
}

如果有人能给我关于如何使这项工作正常工作的建议,我将不胜感激。

更新

我对其进行了修改以检查 for 循环中的所有数字。

void primenumber(int number)
{
    for(int i=1; i<number; i++)
    {
       if(number%i!=0)
          cout<<"Number is prime:"<<endl;
       else 
          cout<<"number is NOt prime"<<endl;
    }  
}

【问题讨论】:

  • 您的代码所做的只是报告该数字是否可被 2 整除。您会使用什么通用方法来检测素数?让我们从它开始,并将其制作成可执行代码。
  • 你有没有想过一个数是质数意味着什么?用伪代码写出来,然后变成真正的代码。

标签: c++ algorithm primes


【解决方案1】:

这是一个确定给定数字是否为素数的 C++ 代码:

bool isPrime(int num)
{
    if(num < 2) return false;
    for(int i = 2; i <= sqrt(num); i++)
        if(num % i == 0) return false;
    return true;
}

PS 不要忘记包含 math.h 库以使用 sqrt 函数

【讨论】:

  • 这样做的方法确实很慢,但我想它可以工作。
【解决方案2】:

这是一个检查一个数是否为素数的简单程序:

#include <iostream>  
using namespace std;  
int main()  
{  
  int n, i, m=0, flag=0;  
  cout << "Enter the Number to check Prime: ";  
  cin >> n;  
  m=n/2;  
  for(i = 2; i <= m; i++)  
  {  
      if(n % i == 0)  
      {  
          cout<<"Number is not Prime."<<endl;  
          flag=1;  
          break;  
      }  
  }  
  if (flag==0)  
      cout << "Number is Prime."<<endl;  
  return 0;  
}

【讨论】:

    【解决方案3】:

    数 6 以提高速度:

    bool isPrime(int n)
    {
        if(n==1) return false;
        if(n==2 || n==3) return true;
        if(n%2==0 || n%3==0) return false;
    
        for(int i=5; i*i<=n; i=i+6)
            if(n%i==0 || n%(i+2)==0)
                return false;
    
        return true;          
    }
    

    【讨论】:

      【解决方案4】:
      //simple function to determine if a number is a prime number
      //to state if it is a prime number
      
      #include <iostream>
      
      using namespace std;
      
      int isPrime(int x); //functioned defined after int main()
      
      int main() {
        int y;
        cout << "enter value" << endl;
      
        cin >> y;
      
        isPrime(y);
      
        return 0;
      
      } //end of main function
      
      //-------------function
      
      int isPrime(int x) {
        int counter = 0;
        cout << "factors of " << x << " are " << "\n\n"; //print factors of the number
      
        for (int i = 0; i <= x; i++)
        {
          for (int j = 0; j <= x; j++)
          {
            if (i * j == x) //check if the number has multiples;
            {
              cout << i << " ,  "; //output provided for the reader to see the
              // muliples
              ++counter; //counts the number of factors
            }
          }
        }
        cout << "\n\n";
      
        if (counter > 2) {
          cout << "value is not a prime number" << "\n\n";
        }
      
        if (counter <= 2) {
          cout << "value is a prime number" << endl;
        }
      }
      

      【讨论】:

      • 这不是一个真正的答案。虽然这可能会或可能不会解决 OP 中描述的问题,但您需要添加更多上下文和解释,说明导致原始问题的原因以及您的解决方案如何解决它。
      • 函数什么都不返回,会出错。
      【解决方案5】:

      这是一个快速有效的方法:

      bool isPrimeNumber(int n) {
          int divider = 2;
          while (n % divider != 0) {
              divider++;
          }
          if (n == divider) {
              return true;
          }
          else {
              return false;
          }
      }
      

      它将开始寻找 n 的可整除数,从 2 开始。一旦找到一个,如果该数等于 n,则 它是素数,否则它不是。

      【讨论】:

        【解决方案6】:

        我想出了这个:

        int counter = 0;
        
        bool checkPrime(int x) {
           for (int y = x; y > 0; y--){
              if (x%y == 0) {
                 counter++;
              }
           }
           if (counter == 2) {
              counter = 0; //resets counter for next input
              return true; //if its only divisible by two numbers (itself and one) its a prime
           }
           else counter = 0;
                return false;
        }
        

        【讨论】:

          【解决方案7】:

          上面有人有以下情况。

          bool check_prime(int num) {
          for (int i = num - 1; i > 1; i--) {
              if ((num % i) == 0)
                  return false;
          }
          return true;
          }
          

          这主要是有效的。我刚刚在 Visual Studio 2017 中对其进行了测试。它会说小于 2 的任何东西也是素数(所以 1、0、-1 等)

          这里稍作修改来纠正这个问题。

          bool check_prime(int number)
          {
              if (number > 1)
              {
                  for (int i = number - 1; i > 1; i--)
                  {
                      if ((number % i) == 0)
                          return false;
                  }
                  return true;
              }
              return false;
          }
          

          【讨论】:

            【解决方案8】:

            C++

            bool isPrime(int number){
                if (number != 2){
                    if (number < 2 || number % 2 == 0) {
                        return false;
                    }
                    for(int i=3; (i*i)<=number; i+=2){
                        if(number % i == 0 ){
                            return false;
                        }
                    }
                }
                return true;
            }
            

            Javascript

            function isPrime(number)
            {
                if (number !== 2) {
                    if (number < 2 || number % 2 === 0) {
                        return false;
                    }
                    for (var i=3; (i*i)<=number; i+=2)
                    {
                        if (number % 2 === 0){
                            return false;
                        }
                    }
                }
                return true;
            }
            

            Python

            def isPrime(number):
                if (number != 2):
                    if (number < 2 or number % 2 == 0):
                        return False
                    i = 3
                    while (i*i) <= number:
                        if(number % i == 0 ):
                            return False;
                        i += 2
                return True;
            

            【讨论】:

            • (i*i)numberINT_MAX 附近的素数时容易溢出。
            【解决方案9】:

            我已经使用这个想法来确定数字是否是素数:

            #include <conio.h> 
            #include <iostream>
            using namespace std;
            int main() {
              int x, a;
              cout << "Enter The No. :";
              cin >> x;
              int prime(unsigned int);
              a = prime(x);
              if (a == 1)
                cout << "It Is A Prime No." << endl;
              else
              if (a == 0)
                cout << "It Is Composite No." << endl;
              getch();
            }
            
            int prime(unsigned int x) {
              if (x == 1) {
                cout << "It Is Neither Prime Nor Composite";
                return 2;
              }
              if (x == 2 || x == 3 || x == 5 || x == 7)
                return 1;
              if (x % 2 != 0 && x % 3 != 0 && x % 5 != 0 && x % 7 != 0)
                return 1;
              else
                return 0;
            }
            

            【讨论】:

            • 它会返回1 for 11 这是素数。
            • 还有 13、17、19 和...
            【解决方案10】:

            如果 n 为 2,则为素数。

            如果 n 为 1,则它不是素数。

            如果 n 是偶数,则它不是素数。

            如果 n 是奇数,大于 2,我们必须检查所有奇数 3..sqrt(n)+1,如果这些数中的任何一个可以整除 n,n 不是素数,否则,n 是素数。

            为了获得更好的性能,我建议使用 Eratosthenes 筛。

            这是代码示例:

            bool is_prime(int n)
            {
              if (n == 2) return true;
              if (n == 1 || n % 2 == 0) return false;
            
              for (int i = 3; i*i < n+1; i += 2) {
                  if (n % i == 0) return false;
              }
            
              return true;
            }
            

            【讨论】:

            • 欢迎来到 SO。请避免仅使用代码的答案,在答案中添加说明会更有帮助。
            • 好。但更好的是for (int i = 3; i &lt; sqrt(n)+1; i=i+2) {
            • @Sneak Solved :)
            • @anatoily_v i*i &lt; n+1i &lt; sqrt(n)+1 相同。
            • i*i &lt; n+1i &lt; sqrt(n+1) 而不是必需的i &lt; sqrt(n) + 1 我不确定n 是否有任何可能的值,这很重要,所以可能你是对的,没关系.
            【解决方案11】:
            bool check_prime(int num) {
                for (int i = num - 1; i > 1; i--) {
                    if ((num % i) == 0)
                        return false;
                }
                return true;
            }
            

            检查任何数字是否为素数

            【讨论】:

              【解决方案12】:

              您需要进行更多检查。现在,您只检查数字是否能被 2 整除。对 2、3、4、5、6,... 直到 number 执行相同操作。提示:使用循环

              解决此问题后,请尝试寻找优化。 提示:您只需检查所有数字,直到数字的平方根

              【讨论】:

              • 还有很多优化。您只需要测试到 SQRT(n),因为如果 n 可以分解为 2 个数字,其中一个必须
              • 在优化时 - 考虑要测试的最高数字。它必须是“数字”还是可以少一点? ;) 编辑:arrrgh,今天人们速度很快 ;)
              • 甚至比跳过偶数更好,您可以跳过所有不小于 1 或大于 6 的倍数的数字。(6 + 2 或 4 的倍数可以被 2 和倍数整除6 + 3 能被 3 整除,只剩下 6 + 1 或 5 的倍数)
              • 您还可以更进一步,根据数值模 30 检查数字,这仍然可以作为展开循环进行。虽然当然,随着你的进步,你会得到递减的回报......(不检查 2 的倍数会将检查的数量减少一半,基于 6 只需要再减少 1/3,达到 30 只会减少另外 1/5 ...)
              • 我尝试了 30 个,但随后在较低数字范围内的成本最终导致算法平均变慢。
              【解决方案13】:
              if(number%2!=0)
                    cout<<"Number is prime:"<<endl;
              

              代码非常错误。 33 除以 2 是 16,提醒 1 但它不是质数...

              【讨论】:

              • 用户已经知道这是错误的,并且已经有多个答案解释了错误的原因以及如何解决它。
              • 我希望他们没有为此等待 4 年
              【解决方案14】:

              使用数学首先找到数字的平方根,然后开始循环,直到平方根后得到的数字结束。 检查每个值是否给定数字可被迭代值整除。如果任何值除以给定数字,则它不是素数,否则为素数。 这是代码

               bool is_Prime(int n)
               {
              
                 int square_root = sqrt(n); // use math.h
                 int toggle = 1;
                 for(int i = 2; i <= square_root; i++)
                 {
                   if(n%i==0)
                   { 
                      toggle = 0;
                      break;
                   }
                 }
              
                 if(toggle)
                   return true;
                 else
                   return false;
              
               } 
              

              【讨论】:

              • 与其将 i 与 sqrt(n) 进行比较,不如将 i*i 与 n 进行比较。
              【解决方案15】:
              bool isPrime(int number){
              
                  if(number < 2) return false;
                  if(number == 2) return true;
                  if(number % 2 == 0) return false;
                  for(int i=3; (i*i)<=number; i+=2){
                      if(number % i == 0 ) return false;
                  }
                  return true;
              
              }
              

              【讨论】:

              • 哟,
              • 是必要的,因为数字可能来自正方形,例如49 = 7^2。
              • (i*i)number 靠近INT_MAX 时容易溢出。
              【解决方案16】:
              #define TRUE 1
              #define FALSE -1
              
              int main()
              {
              /* Local variables declaration */
              int num = 0;
              int result = 0;
              
              /* Getting number from user for which max prime quadruplet value is 
              to be found */
              printf("\nEnter the number :");
              scanf("%d", &num);
              
              result = Is_Prime( num );
              
              /* Printing the result to standard output */
              if (TRUE == result)
                  printf("\n%d is a prime number\n", num);
              else
                  printf("\n%d is not a prime number\n", num);
              
              return 0;
              }
              
              int Is_Prime( int num )
              {
              int i = 0;
              
              /* Checking whether number is negative. If num is negative, making
              it positive */
              if( 0 > num )
                  num = -num;
              
              /* Checking whether number is less than 2 */
              if( 2 > num )
                  return FALSE;
              
              /* Checking if number is 2 */
              if( 2 == num )
                  return TRUE;
              
              /* Checking whether number is even. Even numbers
              are not prime numbers */
              if( 0 == ( num % 2 ))
                  return FALSE;
              
              /* Checking whether the number is divisible by a smaller number
              1 += 2, is done to skip checking divisibility by even numbers.
              Iteration reduced to half */
              for( i = 3; i < num; i += 2 )
                  if( 0 == ( num % i ))
                      /* Number is divisible by some smaller number, 
                      hence not a prime number */
                      return FALSE;
              
              return TRUE;
              }
              

              【讨论】:

              • 您甚至可以使用 for( i = 3; (i*i) &lt; num; i += 2 ) 减少迭代次数 请注意 (i*i) &lt; num 与您基于 i &lt; num 的原始代码相比,如果您更新您的答案,请告诉我...干杯
              • 定义自定义 TRUEFALSE 值对我来说似乎真的很奇怪。
              【解决方案17】:

              我遵循相同的算法但不同的实现,循环到 sqrt(n) 步骤 2 仅奇数,因为我检查它是否可被 2 或 2*k 整除它是错误的。这是我的代码

              public class PrimeTest {
              
                  public static boolean isPrime(int i) {
                      if (i < 2) {
                          return false;
                      } else if (i % 2 == 0 && i != 2) {
                          return false;
                      } else {
                          for (int j = 3; j <= Math.sqrt(i); j = j + 2) {
                              if (i % j == 0) {
                                  return false;
                              }
                          }
                          return true;
                      }
                  }
              
                  /**
                   * @param args
                   */
                  public static void main(String[] args) {
                      for (int i = 1; i < 100; i++) {
                          if (isPrime(i)) {
                              System.out.println(i);
                          }
                      }
                  }
              
              }
              

              【讨论】:

                【解决方案18】:

                我自己的 IsPrime() 函数,基于著名的 Rabin-Miller 算法的确定性变体编写,结合优化的步进暴力破解,为您提供了最快的素数测试函数之一。

                __int64 power(int a, int n, int mod)
                {
                 __int64 power=a,result=1;
                
                 while(n)
                 {
                  if(n&1) 
                   result=(result*power)%mod;
                  power=(power*power)%mod;
                  n>>=1;
                 }
                 return result;
                }
                
                bool witness(int a, int n)
                {
                 int t,u,i;
                 __int64 prev,curr;
                
                 u=n/2;
                 t=1;
                 while(!(u&1))
                 {
                  u/=2;
                  ++t;
                 }
                
                 prev=power(a,u,n);
                 for(i=1;i<=t;++i)
                 {
                  curr=(prev*prev)%n;
                  if((curr==1)&&(prev!=1)&&(prev!=n-1)) 
                   return true;
                  prev=curr;
                 }
                 if(curr!=1) 
                  return true;
                 return false;
                }
                
                inline bool IsPrime( int number )
                {
                 if ( ( (!(number & 1)) && number != 2 ) || (number < 2) || (number % 3 == 0 && number != 3) )
                  return (false);
                
                 if(number<1373653)
                 {
                  for( int k = 1; 36*k*k-12*k < number;++k)
                  if ( (number % (6*k+1) == 0) || (number % (6*k-1) == 0) )
                   return (false);
                
                  return true;
                 }
                
                 if(number < 9080191)
                 {
                  if(witness(31,number)) return false;
                  if(witness(73,number)) return false;
                  return true;
                 }
                
                
                 if(witness(2,number)) return false;
                 if(witness(7,number)) return false;
                 if(witness(61,number)) return false;
                 return true;
                
                 /*WARNING: Algorithm deterministic only for numbers < 4,759,123,141 (unsigned int's max is 4294967296)
                   if n < 1,373,653, it is enough to test a = 2 and 3.
                   if n < 9,080,191, it is enough to test a = 31 and 73.
                   if n < 4,759,123,141, it is enough to test a = 2, 7, and 61.
                   if n < 2,152,302,898,747, it is enough to test a = 2, 3, 5, 7, and 11.
                   if n < 3,474,749,660,383, it is enough to test a = 2, 3, 5, 7, 11, and 13.
                   if n < 341,550,071,728,321, it is enough to test a = 2, 3, 5, 7, 11, 13, and 17.*/
                }
                

                要使用,请将代码复制并粘贴到程序顶部。调用它,它会返回一个 BOOL 值,true 或 false。

                if(IsPrime(number))
                {
                    cout << "It's prime";
                }
                
                else
                {
                    cout<<"It's composite";
                }
                

                如果您在使用“__int64”进行编译时遇到问题,请将其替换为“long”。在VS2008和VS2010下都能正常编译。

                它是如何工作的: 该函数分为三个部分。部分检查是否是罕见的异常之一(负数,1),并拦截程序的运行。

                如果数字小于 1373653,则第二部分开始,这是理论上 Rabin Miller 算法将击败我优化的蛮力函数的数字。然后是两个级别的 Rabin Miller,旨在最大限度地减少所需的证人数量。由于您将要测试的大多数数字都低于 40 亿,因此概率 Rabin-Miller 算法可以通过检查证人 2、7 和 61 来确定。如果您需要超过 40 亿上限,您将需要一个大的number 库,并对 power() 函数应用模数或位移修改。

                如果你坚持使用暴力破解方法,这里只是我优化的暴力破解 IsPrime() 函数:

                inline bool IsPrime( int number )
                {
                 if ( ( (!(number & 1)) && number != 2 ) || (number < 2) || (number % 3 == 0 && number != 3) )
                  return (false);
                
                 for( int k = 1; 36*k*k-12*k < number;++k)
                  if ( (number % (6*k+1) == 0) || (number % (6*k-1) == 0) )
                   return (false);
                  return true;
                 }
                }
                

                这个蛮力作品的工作原理: 所有素数(除了 2 和 3)都可以用 6k+1 或 6k-1 的形式表示,其中 k 是正整数。这段代码使用了这个事实,并以 6k+1 或 6k-1 的形式测试所有数字,小于所讨论数字的平方根。这块集成到我更大的 IsPrime() 函数中(首先显示的函数)。

                如果你需要找出一个数之下的所有素数,找出所有低于 1000 的素数,看看埃拉托色尼筛法。我的另一个最爱。

                作为补充说明,我希望看到有人实现椭圆曲线方法算法,一直想看到用 C++ 实现该算法有一段时间了,但我失去了它的实现。从理论上讲,它甚至比我实现的确定性 Rabin Miller 算法还要快,尽管我不确定这是否适用于 40 亿以下的数字。

                【讨论】:

                • 你的函数只接受 int 类型的参数。如果它接受更大的数字,它将不适用于 > 2^32 的数字。
                【解决方案19】:

                如果你很懒,并且有很多 RAM,请创建一个 sieve of Eratosthenes,它实际上是一个巨大的数组,你可以从中踢出所有非质数。 从那时起,每个主要的“概率”测试都将非常快。 这种快速结果解决方案的上限是您的 RAM 量。此解决方案对于超慢结果的上限是您的硬盘容量。

                【讨论】:

                • 分段工作,你只需要存储你的上限sqrt以下的素数。段数组可以通过使用位、仅使用赔率甚至 2-3-5-coprimes 来进一步缩小。
                • 将所有内容从字节中转换为位,您可以获得 2^3 倍的空间,如果您正在寻找大素数,这是微不足道的。如果你把 2,3,5,7 等素数存储为整数,你必须将这些数字存储为至少 32 位整数,这是一种浪费。
                • 工作 segment 通过窄 segment ...存储 sqrt(N) int 素数是值得的。
                【解决方案20】:

                有几种不同的方法可以解决这个问题。
                “天真”方法:尝试所有(奇数)数直到该数(根)。
                改进的“朴素”方法:仅每 6n ± 1 次尝试一次。
                概率测试:Miller-Rabin、Solovay-Strasse 等。

                哪种方法适合您,取决于您使用素数做什么。
                你至少应该阅读Primality Testing

                【讨论】:

                • 我最喜欢的消遣之一,阅读 Primality Testing。一直是我在数论中最喜欢的科目。哦,你遗漏了确定性测试。 ECM 和 AKS 似乎在该类别中处于领先地位。
                • 是的,我没有列出所有类型的测试。我把它作为练习留给读者。 ;)
                • 每 6n+1 个数字的测试将跳过许多素数。许多素数仅比下一个最高素数小 4 或 2。 (参见关于孪生素数和表亲素数的维基百科文章。)
                • @RichS:您需要再次阅读我的答案...我并不是说您应该只测试6n + 1 数字...我声明您应该测试每个6n ± 1...是6n + 1 AND 6n - 1...这已被证明是正确的...
                • 如果有证据表明 6n +/- 1 有效,您可以发布该证明的链接吗?
                【解决方案21】:

                如果您知道输入的范围(因为您的函数采用int,所以您可以这样做),您可以预先计算一个小于或等于最大输入平方根的素数表 (2^31-1在这种情况下),然后测试表中每个素数小于或等于给定数字的平方根的可分性。

                【讨论】:

                • 这可以通过埃拉托色尼筛来完成,但如果范围太大,系统将无法使用足够的内存。无论如何,一半的内存会被浪费,所有的偶数显然都是复合的。猜猜映射(或双端队列?忘了哪个是 PHP 关联数组的 C++ 等价物)在使用筛子确定素数后存储数字下方的所有素数效果最好。如果它不在数组中,则它是复合的。
                • @LostInTheCode 表中只需要大约 4300 个左右的数字。重读我写的。我没有说要创建一个表格来说明从 1 到 2^31 的每个数字是否是素数——我说只存储从 1 到 sqrt(2^31) 的素数并测试每个数字的可分性数字。
                【解决方案22】:

                此代码仅检查数字是否可被 2 整除。要成为素数,它不能被所有小于自身的整数整除。这可以通过在循环中检查它是否可以被所有小于floor(sqrt(n)) 的整数整除来实现。如果你有兴趣,有很多much faster algorithms 存在。

                【讨论】:

                  【解决方案23】:

                  我猜想使用 sqrt 并运行 foreach frpm 2 到 sqrt+1 if(input% number!=0) return false; 一旦达到 sqrt+1,您就可以确定它的质数。

                  【讨论】:

                    猜你喜欢
                    相关资源
                    最近更新 更多
                    热门标签