C# 确定一个数是否为素数

C# 确定一个数是否为素数,c#,c,primes,C#,C,Primes,我试图想出一个方法,它取一个整数并返回一个布尔值来表示这个数字是素数还是非素数,而我对C知之甚少;有人愿意给我一些建议吗 基本上,我会在C#中这样做: static bool IsPrime(int number) { for (int i = 2; i < number; i++) { if (number % i == 0 && i != number) return false; } return

我试图想出一个方法,它取一个整数并返回一个布尔值来表示这个数字是素数还是非素数,而我对C知之甚少;有人愿意给我一些建议吗

基本上,我会在C#中这样做:

static bool IsPrime(int number)
{
    for (int i = 2; i < number; i++)
    {
        if (number % i == 0 && i != number)
            return false;
    }
    return true;
}
int IsPrime(unsigned int number) {
    if (number <= 1) return 0; // zero and one are not prime
    if ((number > 2) && ((number % 2) == 0)) return 0; //no even number is prime number (bar 2)
    unsigned int i;
    for (i=2; i*i<=number; i++) {
        if (number % i == 0) return 0;
    }
    return 1;
}
static bool IsPrime(整数)
{
for(int i=2;i
好的,那么忘掉C吧。假设我给你一个数字,让你确定它是否是素数。你是怎么做到的?清楚地写下步骤,然后担心将它们翻译成代码

一旦确定了算法,您就可以更容易地了解如何编写程序,其他人也可以帮助您编写程序

编辑:以下是您发布的C代码:

static bool IsPrime(int number) {
    for (int i = 2; i < number; i++) {
        if (number % i == 0 && i != number) return false;
    }
    return true;
}
这是一个完全有效的C程序,可以实现您想要的功能。我们可以不费吹灰之力地稍微改进一下。首先,请注意
i
总是小于
number
,因此检查
i!=编号
始终成功;我们可以摆脱它

此外,您实际上不需要一直尝试除数,直到
number-1
;您可以在到达sqrt(编号)时停止检查。由于
sqrt
是一个浮点运算,它带来了一大堆微妙之处,因此我们实际上不会计算
sqrt(number)
。相反,我们可以检查
i*i
  • 建立一个小素数表,并检查它们是否除以您的输入数
  • 如果数字保留为1,则尝试使用递增基进行伪素性测试。例如,见
  • 如果你的数存活到2,如果它低于一些已知的界限,你就可以断定它是素数。否则,您的答案将仅为“可能是素数”。您将在wiki页面中找到这些边界的一些值

  • 检查从2到要检查的数字的根的每个整数的模

    如果模等于零,它就不是素数

    伪代码:

    bool IsPrime(int target)
    {
      for (i = 2; i <= root(target); i++)
      {
        if ((target mod i) == 0)
        {
          return false;
        }
      }
    
      return true;
    }
    
    bool-IsPrime(int-target)
    {
    
    对于(i=2;i我很惊讶没有人提到这一点

    使用

    详情:

  • 基本上,非质数可以被除1和自身之外的另一个数整除
  • 因此:非质数是质数的乘积
  • Eratosthenes筛找到一个素数并存储它。当一个新的素数被检查为素数时,所有先前的素数都会根据已知素数列表进行检查

    原因:

  • 此算法/问题称为“”
  • 它创建一个素数集合
  • 这是一个动态规划问题的例子
  • 很快

  • 我要补充的是,偶数(第2栏)不能是素数。这会导致for循环之前的另一种情况。因此,结束代码应该如下所示:

    static bool IsPrime(int number)
    {
        for (int i = 2; i < number; i++)
        {
            if (number % i == 0 && i != number)
                return false;
        }
        return true;
    }
    
    int IsPrime(unsigned int number) {
        if (number <= 1) return 0; // zero and one are not prime
        if ((number > 2) && ((number % 2) == 0)) return 0; //no even number is prime number (bar 2)
        unsigned int i;
        for (i=2; i*i<=number; i++) {
            if (number % i == 0) return 0;
        }
        return 1;
    }
    
    intisprime(无符号整数){
    如果(数字2)和((数字%2)==0))返回0;//没有偶数是素数(条2)
    无符号整数i;
    对于(i=2;i*i
    int是素数(int-val)
    {
    内部分区,正方形;
    如果(val==2)返回TRUE;/*2为素数*/
    如果((val&1)==0)返回FALSE;/*则任何其他偶数都不是*/
    div=3;
    平方=9;/*3*3*/
    而(平方,E*O=>E,O*E=>E和O*O=>O)


    除法/模在x86体系结构上的成本确实很高,尽管成本各不相同(请参阅)。另一方面,乘法非常便宜。

    Stephen Canon回答得非常好

    但是

    • 通过观察所有素数的形式为6k±1(2和3除外),可以进一步改进该算法
    • 这是因为对于某些整数k和i=−1、0、1、2、3或4;2次除法(6k+0)、(6k+2)、(6k+4)和3次除法(6k+3)
    • 因此,一个更有效的方法是测试n是否可以被2或3整除,然后检查所有形式为6k±1的数字≤ √n
    • 这是测试所有m到的速度的3倍√n

      int IsPrime(unsigned int number) {
          if (number <= 3 && number > 1) 
              return 1;            // as 2 and 3 are prime
          else if (number%2==0 || number%3==0) 
              return 0;     // check if number is divisible by 2 or 3
          else {
              unsigned int i;
              for (i=5; i*i<=number; i+=6) {
                  if (number % i == 0 || number%(i + 2) == 0) 
                      return 0;
              }
              return 1; 
          }
      }
      
      intisprime(无符号整数){
      如果(1号)
      返回1;//因为2和3是素数
      else if(数字%2==0 | |数字%3==0)
      返回0;//检查数字是否可以被2或3整除
      否则{
      无符号整数i;
      
      对于(i=5;i*i这个程序对于检查单个数字的素性非常有效

      bool check(int n){
          if (n <= 3) {
              return n > 1;
          }
      
          if (n % 2 == 0 || n % 3 == 0) {
              return false;
          }
              int sq=sqrt(n); //include math.h or use i*i<n in for loop
          for (int i = 5; i<=sq; i += 6) {
              if (n % i == 0 || n % (i + 2) == 0) {
                  return false;
              }
          }
      
          return true;
      }
      
      bool检查(int n){
      if(n1;
      }
      如果(n%2==0 | | n%3==0){
      返回false;
      }
      
      int sq=sqrt(n);//包含math.h或使用i*i读了这个问题后,我被以下事实所吸引:一些答案通过以2*3=6的倍数运行循环来提供优化

      所以我用同样的想法创建了一个新函数,但是它的倍数是2*3*5=30

      int check235(unsigned long n)
      {
          unsigned long sq, i;
      
          if(n<=3||n==5)
              return n>1;
      
          if(n%2==0 || n%3==0 || n%5==0)
              return 0;
      
          if(n<=30)
              return checkprime(n); /* use another simplified function */
      
          sq=ceil(sqrt(n));
          for(i=7; i<=sq; i+=30)
              if (n%i==0 || n%(i+4)==0 || n%(i+6)==0 || n%(i+10)==0 || n%(i+12)==0 
                 || n%(i+16)==0 || n%(i+22)==0 || n%(i+24)==0)
                  return 0;
      
              return 1;
      }
      
      所以我想,如果广义化的话,会不会有人得到太多?我提出了一个函数,它将首先对给定的原始素数列表进行包围,然后用这个列表来计算更大的素数

      int checkn(unsigned long n, unsigned long *p, unsigned long t)
      {
          unsigned long sq, i, j, qt=1, rt=0;
          unsigned long *q, *r;
      
          if(n<2)
              return 0;
      
          for(i=0; i<t; i++)
          {
              if(n%p[i]==0)
                  return 0;
              qt*=p[i];
          }
          qt--;
      
          if(n<=qt)
              return checkprime(n); /* use another simplified function */
      
          if((q=calloc(qt, sizeof(unsigned long)))==NULL)
          {
              perror("q=calloc()");
              exit(1);
          }
          for(i=0; i<t; i++)
              for(j=p[i]-2; j<qt; j+=p[i])
                  q[j]=1;
      
          for(j=0; j<qt; j++)
              if(q[j])
                  rt++;
      
          rt=qt-rt;
          if((r=malloc(sizeof(unsigned long)*rt))==NULL)
          {
              perror("r=malloc()");
              exit(1);
          }
          i=0;
          for(j=0; j<qt; j++)
              if(!q[j])
                  r[i++]=j+1;
      
          free(q);
      
          sq=ceil(sqrt(n));
          for(i=1; i<=sq; i+=qt+1)
          {
              if(i!=1 && n%i==0)
                  return 0;
              for(j=0; j<rt; j++)
                  if(n%(i+r[j])==0)
                      return 0;
          }
          return 1;
      }
      

      顺便说一句,我并不是有意释放(r),将此任务交给操作系统,因为程序一退出内存就会释放,以获得一些时间。但如果您打算在计算后继续运行代码,则释放内存是明智的


      奖金

      int check2357(unsigned long n)
      {
          unsigned long sq, i;
      
          if(n<=3||n==5||n==7)
              return n>1;
      
          if(n%2==0 || n%3==0 || n%5==0 || n%7==0)
              return 0;
      
          if(n<=210)
              return checkprime(n); /* use another simplified function */
      
          sq=ceil(sqrt(n));
          for(i=11; i<=sq; i+=210)
          {    
              if(n%i==0 || n%(i+2)==0 || n%(i+6)==0 || n%(i+8)==0 || n%(i+12)==0 || 
         n%(i+18)==0 || n%(i+20)==0 || n%(i+26)==0 || n%(i+30)==0 || n%(i+32)==0 || 
         n%(i+36)==0 || n%(i+42)==0 || n%(i+48)==0 || n%(i+50)==0 || n%(i+56)==0 || 
         n%(i+60)==0 || n%(i+62)==0 || n%(i+68)==0 || n%(i+72)==0 || n%(i+78)==0 || 
         n%(i+86)==0 || n%(i+90)==0 || n%(i+92)==0 || n%(i+96)==0 || n%(i+98)==0 || 
         n%(i+102)==0 || n%(i+110)==0 || n%(i+116)==0 || n%(i+120)==0 || n%(i+126)==0 || 
         n%(i+128)==0 || n%(i+132)==0 || n%(i+138)==0 || n%(i+140)==0 || n%(i+146)==0 || 
         n%(i+152)==0 || n%(i+156)==0 || n%(i+158)==0 || n%(i+162)==0 || n%(i+168)==0 || 
         n%(i+170)==0 || n%(i+176)==0 || n%(i+180)==0 || n%(i+182)==0 || n%(i+186)==0 || 
         n%(i+188)==0 || n%(i+198)==0)
                  return 0;
          }
          return 1;
      }
      

      使用Eratosthenes筛,计算速度比“已知范围”的素数算法要快得多

      通过使用wiki()中的伪代码,我能够在C#上获得解决方案

      public bool IsPrimeNumber(int val){
      //使用Eratosthenes筛。
      if(val<2)
      {
      返回false;
      }
      //为val+1保留位置并设置为true。
      var标记=新布尔值[val+1];
      
      对于(var i=2;i避免溢出错误

      unsigned i, number;
      ...
      for (i=2; i*i<=number; i++) {  // Buggy
      for (i=2; i*i<=number; i += 2) {  // Buggy
      // or
      for (i=5; i*i<=number; i+=6) { // Buggy
      

      当然,这更像是一个数学问题,而不是一个编程问题?这里有一些提示:int*ptr;int*ptr2;int*ptr3。对不起,没办法。你要检查的数字有多大?还有
      int checkn(unsigned long n, unsigned long *p, unsigned long t)
      {
          unsigned long sq, i, j, qt=1, rt=0;
          unsigned long *q, *r;
      
          if(n<2)
              return 0;
      
          for(i=0; i<t; i++)
          {
              if(n%p[i]==0)
                  return 0;
              qt*=p[i];
          }
          qt--;
      
          if(n<=qt)
              return checkprime(n); /* use another simplified function */
      
          if((q=calloc(qt, sizeof(unsigned long)))==NULL)
          {
              perror("q=calloc()");
              exit(1);
          }
          for(i=0; i<t; i++)
              for(j=p[i]-2; j<qt; j+=p[i])
                  q[j]=1;
      
          for(j=0; j<qt; j++)
              if(q[j])
                  rt++;
      
          rt=qt-rt;
          if((r=malloc(sizeof(unsigned long)*rt))==NULL)
          {
              perror("r=malloc()");
              exit(1);
          }
          i=0;
          for(j=0; j<qt; j++)
              if(!q[j])
                  r[i++]=j+1;
      
          free(q);
      
          sq=ceil(sqrt(n));
          for(i=1; i<=sq; i+=qt+1)
          {
              if(i!=1 && n%i==0)
                  return 0;
              for(j=0; j<rt; j++)
                  if(n%(i+r[j])==0)
                      return 0;
          }
          return 1;
      }
      
      $ time ./testprimebool.x 18446744065119617029 2 3 5
      f(2,3,5)
      Yes, its prime.
      real    0m12.668s
      user    0m12.680s
      sys     0m0.000s
      
      $ time ./testprimebool.x 18446744065119617029 2 3 5 7
      f(2,3,5,7)
      Yes, its prime.
      real    0m10.889s
      user    0m10.900s
      sys     0m0.000s
      
      $ time ./testprimebool.x 18446744065119617029 2 3 5 7 11
      f(2,3,5,7,11)
      Yes, its prime.
      real    0m10.021s
      user    0m10.028s
      sys     0m0.000s
      
      $ time ./testprimebool.x 18446744065119617029 2 3 5 7 11 13
      f(2,3,5,7,11,13)
      Yes, its prime.
      real    0m9.351s
      user    0m9.356s
      sys     0m0.004s
      
      $ time ./testprimebool.x 18446744065119617029 2 3 5 7 11 13 17
      f(2,3,5,7,11,13,17)
      Yes, its prime.
      real    0m8.802s
      user    0m8.800s
      sys     0m0.008s
      
      $ time ./testprimebool.x 18446744065119617029 2 3 5 7 11 13 17 19
      f(2,3,5,7,11,13,17,19)
      Yes, its prime.
      real    0m8.614s
      user    0m8.564s
      sys     0m0.052s
      
      $ time ./testprimebool.x 18446744065119617029 2 3 5 7 11 13 17 19 23
      f(2,3,5,7,11,13,17,19,23)
      Yes, its prime.
      real    0m13.013s
      user    0m12.520s
      sys     0m0.504s
      
      $ time ./testprimebool.x 18446744065119617029 2 3 5 7 11 13 17 19 23 29
      f(2,3,5,7,11,13,17,19,23,29)                                                                                                                         
      q=calloc(): Cannot allocate memory
      
      int check2357(unsigned long n)
      {
          unsigned long sq, i;
      
          if(n<=3||n==5||n==7)
              return n>1;
      
          if(n%2==0 || n%3==0 || n%5==0 || n%7==0)
              return 0;
      
          if(n<=210)
              return checkprime(n); /* use another simplified function */
      
          sq=ceil(sqrt(n));
          for(i=11; i<=sq; i+=210)
          {    
              if(n%i==0 || n%(i+2)==0 || n%(i+6)==0 || n%(i+8)==0 || n%(i+12)==0 || 
         n%(i+18)==0 || n%(i+20)==0 || n%(i+26)==0 || n%(i+30)==0 || n%(i+32)==0 || 
         n%(i+36)==0 || n%(i+42)==0 || n%(i+48)==0 || n%(i+50)==0 || n%(i+56)==0 || 
         n%(i+60)==0 || n%(i+62)==0 || n%(i+68)==0 || n%(i+72)==0 || n%(i+78)==0 || 
         n%(i+86)==0 || n%(i+90)==0 || n%(i+92)==0 || n%(i+96)==0 || n%(i+98)==0 || 
         n%(i+102)==0 || n%(i+110)==0 || n%(i+116)==0 || n%(i+120)==0 || n%(i+126)==0 || 
         n%(i+128)==0 || n%(i+132)==0 || n%(i+138)==0 || n%(i+140)==0 || n%(i+146)==0 || 
         n%(i+152)==0 || n%(i+156)==0 || n%(i+158)==0 || n%(i+162)==0 || n%(i+168)==0 || 
         n%(i+170)==0 || n%(i+176)==0 || n%(i+180)==0 || n%(i+182)==0 || n%(i+186)==0 || 
         n%(i+188)==0 || n%(i+198)==0)
                  return 0;
          }
          return 1;
      }
      
      $ time ./testprimebool.x 18446744065119617029 7
      h(2,3,5,7)
      Yes, its prime.
      real    0m9.123s
      user    0m9.132s
      sys     0m0.000s
      
      public bool IsPrimeNumber(int val) {
          // Using Sieve of Eratosthenes.
          if (val < 2)
          {
              return false;
          }
      
          // Reserve place for val + 1 and set with true.
          var mark = new bool[val + 1];
          for(var i = 2; i <= val; i++)
          {
              mark[i] = true;
          }
      
          // Iterate from 2 ... sqrt(val).
          for (var i = 2; i <= Math.Sqrt(val); i++)
          {
              if (mark[i])
              {
                  // Cross out every i-th number in the places after i (all the multiples of i).
                  for (var j = (i * i); j <= val; j += i)
                  {
                      mark[j] = false;
                  }
              }
          }
      
          return mark[val];
      }
      
      unsigned i, number;
      ...
      for (i=2; i*i<=number; i++) {  // Buggy
      for (i=2; i*i<=number; i += 2) {  // Buggy
      // or
      for (i=5; i*i<=number; i+=6) { // Buggy
      
      bool IsPrime(unsigned number) {
          for(unsigned i = 2; i <= number/i; i++){
              if(number % i == 0){
                  return false;
              }
          }
          return number >= 2;
      }