C 素数算法

C 素数算法,c,algorithm,optimization,primes,sieve-of-eratosthenes,C,Algorithm,Optimization,Primes,Sieve Of Eratosthenes,有人能告诉我如何用C语言实现算法吗?我需要生成素数,但我的算法很慢 我的代码: #include <stdio.h> int prime(long int i) { long int j; int state = 1; for(j=2;j<i;j++) { if((i%j)==0){state=0;break;} } return state; } int main() { int t; lon

有人能告诉我如何用C语言实现算法吗?我需要生成素数,但我的算法很慢

我的代码:

#include <stdio.h>

int prime(long int i)
{
    long int j;
    int state = 1;
    for(j=2;j<i;j++)
    {
        if((i%j)==0){state=0;break;}
    }
    return state;
}

int main()
{
    int t;
    long int m,n,i;
    scanf("%d", &t);
    while(t--) {
        scanf("%d %d", &m,&n);
        for(i=m;i<=n;i++)
        {
            if(i==1){
                //do nothing for 1
            } else{
                if(prime(i))printf("%d\n",i);
            }
        }
    }
    return 0;
}
#包括
整数素数(长整数i)
{
long-int-j;
int state=1;

对于(j=2;j,您需要创建一个布尔数组,其大小与您要查找的最大素数相同。开始时,它完全初始化为true

如果
i
是素数,则该数组的
i
第个单元格将为真,如果不是,则为假

i=2
开始迭代:它是素数,然后将索引倍数为2的任何单元格设置为false。转到下一个素数(
i=3
)并执行相同操作。转到下一个素数(它是
i=5
i=4
不是素数:
array[4]
在处理
i=2
时被设置为false)一次又一次地做同样的事情。

Marc B's展示了一个很好的简单算法,它是正确的,由NSLogan编写。我对它做了一点修改,以显示一些大小/速度的权衡。出于兴趣的考虑,我想与大家分享一下

首先,守则:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <time.h>

#define USE_BITS

#ifdef USE_BITS
#define alloc_prime char *prime = calloc(i/8+1,sizeof(*prime));
#define set_not_prime(x) prime[x/8]|= (1<<(x%8))
#define is_prime(x) (!(prime[x/8]&(1<<(x%8))))
#endif

#ifdef USE_CHAR
#define alloc_prime char *prime = calloc(i+1,sizeof(*prime));
#define set_not_prime(x) prime[x] = 1
#define is_prime(x) (prime[x] == 0)
#endif

#ifdef USE_SIZE_TYPE
#define alloc_prime size_t *prime = calloc(i+1,sizeof(*prime));
#define set_not_prime(x) prime[x] = 1
#define is_prime(x) (prime[x] == 0)
#endif

 
int main(){
    int i;
    printf("Find primes up to: ");
    scanf("%i",&i);
 
    clock_t start, stop;
    double t = 0.0;
       
    assert((start = clock())!=-1);
       
    //create prime list
    alloc_prime;
    int c1, c2, c3;
    if(!prime){
    printf("Can't allocate %zu bytes.\n",i*sizeof(*prime));
    exit(1);
    }
       
    //set 0 and 1 as not prime
    set_not_prime(0);
    set_not_prime(1);

    //find primes then eliminate their multiples (0 = prime, 1 = composite)
    for(c2 = 2;c2 <= (int)sqrt(i)+1;c2++){
      if(is_prime(c2)){
        c1=c2;
        for(c3 = 2*c1;c3 <= i+1; c3 += c1){
          set_not_prime(c3);
        }
      }
    }
       
    stop = clock();
    t = (double) (stop-start)/CLOCKS_PER_SEC;
       
    //print primes
    for(c1 = 0; c1 < i+1; c1++){
        if(is_prime(c1))printf("%i\n",c1);
    }
    printf("Run time: %f\n", t); //print time to find primes

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#定义和使用字节
#ifdef使用_位
#定义alloc_prime char*prime=calloc(i/8+1,sizeof(*prime));

#定义set_not_prime(x)prime[x/8]|=(1在我看来,您的算法很慢,因为您计算的是非本质数。 试试这个代码

int isPrime(int number){

    if(number < 2) return 0;
    if(number == 2) return 1;
    if(number % 2 == 0) return 0;
    for(int i=3; (i*i)<=number; i+=2){
        if(number % i == 0 ) return 0;
    }
    return 1;

}
int-isPrime(int-number){
如果(数字<2)返回0;
如果(number==2)返回1;
如果(数字%2==0)返回0;

对于(inti=3;(i*i)虽然这是一篇非常古老的文章,但下面是我尝试使用“Eratosthenes筛”算法生成素数的尝试

#include <stdio.h>

#define NUM 8000        /* Prime Numbers in the Range.  'Range + 2' actually. */

int main()
{
  int a[NUM] = {0};         /* Array which is going to hold all the numbers */
  int i , j;

  /* initializing array from 2 to given number + 2, assuming the first prime number is 2 */
  for(i = 2,j=0; i < NUM+2, j<NUM; i++, j++) 
  {
    a[j] =i;
  }


  for(i = 0; i < NUM; i++ ) 
  {
    int num = a[i];

    /* If number is not 0 then only update the later array index. */
    if(num != 0) 
    {
      for (j = i+1; j < NUM; j++) 
      {
        if( (a[j]%num == 0) ) 
        {
            a[j]=0;
        }
      }
    }
  }


  for(i = 0; i < NUM; i++) 
  {
    /* Print all the non Zero *Prime numbers* */
    if(a[i] != 0) 
    {
      printf("%d \n", a[i]);
    }
  }

}
#包括
#定义范围内的NUM 8000/*素数。实际上,范围为+2*/
int main()
{
int一个[NUM]={0};/*数组,它将保存所有数字*/
int i,j;
/*假设第一个素数为2,则将数组从2初始化为给定数+2*/

对于(i=2,j=0;iint

int is_prime(int n){
  int p;
  for(p = 2; p < n; p++){
    if(n % p ==0 && p != n)
      return 0;    
  }
  return 1;
}
int是素数(int n){
INTP;
对于(p=2;p
第一步是要认识到,将其拆分为任意大小的块是很简单的;并且您不需要为每个数字都使用数组(或位字段)。例如,如果您只关心100000到110000之间的数字,那么要将所有可被3整除的数字标记为“非素数”,您可以为(index=3*(100000+3-1)执行
/3、 索引<110000;索引+=3){
”。有关更灵活的示例:

    for( value = 2; value < sqrt( block_end_value-1); value++ ) {
        for( index = value  * (block_state_value+value -1)/value; index < block_end_value; index += value ) {
            mark_not_prime(index - block_state_value);
        }
    }
for(值=2;值
第二步是认识到你不需要关心每一个数字(并且上面的
for(value=2;value
是无效的)。例如,如果你已经将可被2整除的数字标记为“非素数”那么就没有理由关心数字是否可以被4、6或8整除;如果你已经将可以被3整除的数字标记为“非素数”那么就没有理由关心数字是否可以被6、9或12整除;而且……基本上你只想测试一个数字是否可以被另一个素数整除。这意味着要找到100000到110000范围内的素数,你首先要找到0到sqrt(110000)范围内的素数;如果要查找0到sqrt(110000)范围内的素数,则要查找0到sqrt(sqrt(110000))范围内的素数;以及

第三步是认识到复制重复模式可以加快速度。您可以创建一个2位模式(表示“可被2整除”),并将这2位复制到所有位置。同样,您可以创建一个6位模式(表示“可被2或3整除”)用同样的方法,你可以创建一个39916800位的模式(表示“可被2、3、4、5、6、7、8、9、10和11整除”),然后到处复制这个39916800位的模式。当然,没有什么可以阻止你预先生成一个模式并将其存储在程序代码中

第四步是认识到2的倍数太小而无法存储,通过不存储它们,可以将所有表和模式(以及任何存储/预生成的模式)的内存消耗减半

通过组合上述第三和第四步,表示“可被2、3、4、5、6、7、8、9、10和11整除”的预生成模式将花费19958400位,或大约2.38 MiB。该模式的第一部分本身也可用于查找从1到大于11的第一个素数的素数(在本例中为1到13之间的数字)

第五步是认识到,如果您已经有了一个模式,您可以使用它来查找“
N=next”尚未标记的“prime number
”,将现有模式复制N次,然后将N的倍数标记为“not prime”;最后得到一个更大的模式。例如,如果您有一个表示“可被2、3、4、5、6、7、8、9、10和11整除”,您可以跳过12(因为根据现有模式它不是素数);将模式复制13次,然后将可被13整除的数字标记为“非素数”,并以表示“可被2、3、4、5、6、7、8、9、10、11、12和13整除”的模式结束

第六步是要意识到,一旦你有了一个足够大的模式来满足你想要的范围,你就可以在不复制的情况下填充缺少的除数。例如,如果你只想要1到6227020800范围内的素数,那么你可以取一个表示“可被2、3、4、5、6、7、8、9、10、11、12和13整除”的模式然后标记可被素数整除的数
int isPrime(int number){
    if(number < 2) return 0;
    if(number == 2) return 1;
    if(number % 2 == 0) return 0;
    int j;
    for(int i=3; ((j=number/i) >= i); i+=2){
        if(number - (j * i) == 0 ) return 0;
    }
    return 1;
}