C 素数算法
有人能告诉我如何用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
#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;
}