int prime(unsigned long long n){
unsigned val=1, divisor=7;
if(n==2 || n==3) return 1; //n=2, n=3 (special cases).
if(n<2 || !(n%2 && n%3)) return 0; //if(n<2 || n%2==0 || n%3==0) return 0;
for(; divisor<=n/divisor; val++, divisor=6*val+1) //all primes take the form 6*k(+ or -)1, k[1, n).
if(!(n%divisor && n%(divisor-2))) return 0; //if(n%divisor==0 || n%(divisor-2)==0) return 0;
return 1;
}
以上代码是朋友为获得素数而写的内容。它似乎正在使用某种筛分,但我不确定它是如何起作用的。下面的代码是我不那么棒的版本。我会使用sqrt
作为我的循环,但我看到他做了其他事情(可能是筛选相关的),所以我没有打扰。
int prime( unsigned long long n ){
unsigned i=5;
if(n < 4 && n > 0)
return 1;
if(n<=0 || !(n%2 || n%3))
return 0;
for(;i<n; i+=2)
if(!(n%i)) return 0;
return 1;
}
我的问题是:他究竟在做什么?
答案 0 :(得分:5)
你朋友的代码正在利用N&gt;的事实。 3,所有素数采用(6×M±1)的形式,M = 1,2,...(因此,对于M = 1,主要候选者是N = 5和N = 7,并且这两者都是素数) 。此外,所有素数对都是5和7.这只检查每3个奇数中的2个,而你的解决方案检查3个奇数中的3个。
你朋友的代码正在使用分区来实现类似于平方根的东西。也就是说,条件divisor <= n / divisor
或多或少等于,但比溢出更慢,更安全,divisor * divisor <= n
。在循环外使用unsigned long long max = sqrt(n);
可能更好。与您提出的搜索更多可能值的解决方案相比,这大大减少了检查量。平方根检查依赖于以下事实:如果N是复合的,那么对于给定的一对因子F和G(使得F×G = N),其中一个将小于或等于N的平方根并且另一个将大于或等于N的平方根。
正如Michael Burr指出的那样,朋友的主要功能将25(5×5)和35(5×7)识别为素数,并且在1000以下产生177个数字作为素数,而我相信,只有168该范围内的素数。其他错误识别的复合材料有121(11×11),143(13×11),289(17×17),323(17×19),841(29×29),899(29×31)。
测试代码:
#include <stdio.h>
int main(void)
{
unsigned long long c;
if (prime(2ULL))
printf("2\n");
if (prime(3ULL))
printf("3\n");
for (c = 5; c < 1000; c += 2)
if (prime(c))
printf("%llu\n", c);
return 0;
}
原始代码的问题在于它会过早停止检查,因为divisor
设置为要检查的两个数字中较大的而不是较小的数字。
static int prime(unsigned long long n)
{
unsigned long long val = 1;
unsigned long long divisor = 5;
if (n == 2 || n == 3)
return 1;
if (n < 2 || n%2 == 0 || n%3 == 0)
return 0;
for ( ; divisor<=n/divisor; val++, divisor=6*val-1)
{
if (n%divisor == 0 || n%(divisor+2) == 0)
return 0;
}
return 1;
}
请注意,修订版本更容易理解,因为它不需要解释尾部注释中的简写否定条件。另请注意循环体中的+2
而不是-2
。
答案 1 :(得分:2)
他正在检查基础6k + 1 / 6k-1,因为所有素数都可以用该形式表示(并且所有整数都可以以6k + n的形式表示,其中-1 <= n <= 4) 。所以是的,它是一种筛分形式......但不是严格意义上的。
答案 2 :(得分:1)
如果6k + -1部分令人困惑,请注意您可以对大多数6k+n
形式执行某些分解,有些显然是复合的,有些需要进行测试。
考虑数字:
6k + 0 - &gt;复合
6k + 1 - &gt;显然不是复合材料
6k + 2 - &gt; 2(3k + 1) - &gt;复合
6k + 3 - &gt; 3(2k + 1) - &gt;复合
6k + 4 - &gt; 2(3k + 2) - &gt;复合
6k + 5 - >显然不是复合
之前我没有看过这个小技巧,所以它很整洁,但实用性有限,因为sieve of Eratosthenese更有效地找到许多小素数和更大的素数{ {3}}
答案 3 :(得分:0)
#include<stdio.h>
int main()
{
int i,j;
printf("enter the value :");
scanf("%d",&i);
for (j=2;j<i;j++)
{
if (i%2==0 || i%j==0)
{
printf("%d is not a prime number",i);
return 0;
}
else
{
if (j==i-1)
{
printf("%d is a prime number",i);
}
else
{
continue;
}
}
}
}
答案 4 :(得分:-1)
#include<stdio.h>
int main()
{
int n, i = 3, count, c;
printf("Enter the number of prime numbers required\n");
scanf("%d",&n);
if ( n >= 1 )
{
printf("First %d prime numbers are :\n",n);
printf("2\n");
}
for ( count = 2 ; count <= n ; )
{
for ( c = 2 ; c <= i - 1 ; c++ )
{
if ( i%c == 0 )
break;
}
if ( c == i )
{
printf("%d\n",i);
count++;
}
i++;
}
return 0;
}