我试图找到n
之后的第一个素数,除非输入的n
已经是素数(然后程序打印出n
并终止)。
示例输入:
n = 7
The first prime number is: 7
(好)
n = 591
The first prime number is: 591
(不正确,591不是质数)
n = 14
The first prime number is: 15
(这也是错误的,不是17吗?)
我在哪里出错?这可能是显而易见的,但是我才刚开始。
#include <stdio.h>
int main(){
int i = 2, n, m;
printf("n = ");
do
scanf("%d", &n);
while (n < 2);
m = n / 2;
if (n == 2){
printf("The first prime number is: %d", n);
return 0;
}
while ( i <= m ){
if (n % i == 0)
n++;
if (n % i != 0){
printf("The first prime number is: %d", n);
return 0;
} else i++;
}
return 0;
}
答案 0 :(得分:2)
您确定质数的逻辑是错误的。
首先,您应该编写一个函数(不一定是推荐的),以检查一个数字是否为质数。这是此功能的代码:
int checkPrimeNumber(int n)
{
int j, flag = 1;
for(j=2; j <= n/2; ++j)
{
if (n%j == 0)
{
flag =0;
break;
}
}
return flag;
}
一旦包含函数,您的while循环应循环执行,直到使用该函数找到从N开始的第一个质数为止。下面是该函数的代码。
您也可以在这里查看以下答案: https://codereview.stackexchange.com/questions/71212/find-smallest-prime-number-greater-than-given-n
答案 1 :(得分:2)
以下两个逻辑应该可以解决您的问题。
int IsPrime(int n)
{
int i;
for( i=2; i <= n/i; i++)
if( n%i == 0 ) return 0;
return 1;
}
此函数可以合理地快速确定传入的整数是否为素数。通过测试整数的平方根后,它将停止测试。
int FirstPrime(int n)
{
while( !IsPrime(n) )
n++;
return n;
}
此函数包含您的问题陈述中列出的基本逻辑:返回输入值(如果为质数),或者使该值后的第一个整数为质数失败。
将代码分成单独的函数可以使测试和推理代码变得更加容易。
答案 2 :(得分:0)
这是我用于检测素数的简单代码:
int isprime(unsigned number)
{
if (number <= 1)
return 0;
if (number == 2 || number == 3)
return 1;
if (number % 2 == 0 || number % 3 == 0)
return 0;
for (unsigned x = 5; x * x <= number; x += 6)
{
if (number % x == 0 || number % (x + 2) == 0)
return 0;
}
return 1;
}
它利用了一个事实,即所有大于3的素数都具有6N±1的形式。很容易明白为什么。形式6N + 0、6N + 2、6N + 4的所有数字都可以清楚地除以2,形式6N + 3的数字可以清楚地被3除尽,从而仅留下6N + 1和6N + 5作为质数—和6N + 5等效于6(N + 1)-1,因此公式6N±1正确覆盖了它们。对于N = 1,6N±1产生5和7,它们是素数; N = 2产生素数11和13; N = 3产生质数17和19; N = 4产生23和25,其中23是质数,而25不是。所有大于3的素数均具有6N±1的形式;并非所有形式为6N±1的数字都是质数。所有这些意味着,代码在遍历范围直至数字的平方根时,只会检查每六个中的两个除数。
我有一个更复杂的变体,它知道素数最多为100,然后每6步一次:
int isprime(unsigned number)
{
if (number <= 1)
return 0;
if (number == 2 || number == 3)
return 1;
if (number % 2 == 0 || number % 3 == 0)
return 0;
static const unsigned int small_primes[] =
{
5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
53, 59, 61, 67, 71, 73, 79, 83, 87, 89, 91, 97
};
enum { NUM_SMALL_PRIMES = sizeof(small_primes) / sizeof(small_primes[0]) };
for (unsigned i = 0; i < NUM_SMALL_PRIMES; i++)
{
if (number == small_primes[i])
return 1;
if (number % small_primes[i] == 0)
return 0;
}
for (unsigned i = 101; i * i <= number; i += 6)
{
if (number % i == 0 || number % (i + 2) == 0)
return 0;
}
return 1;
}
这通常比另一个要快一些,但数量很少。
我最初是为另一个SO问题编写此代码的,但在发布答案之前已将其删除。它使用isprime()
的另一个变体,其质数表最大为1013。
/* Inspired by the deleted question SO 5308-6674 */
/* Determine the next prime after a given number */
#include <assert.h>
#include <stdio.h>
#include <limits.h>
#include <stdbool.h>
#define NEXT_PRIME_AFTER /* Avoid unnecessary checks in is_prime() */
#ifdef TEST
static unsigned primes[] = { 2, 3, 5, 7, 11 };
#else
static unsigned primes[] =
{
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013,
};
#endif /* TEST */
enum { N_PRIMES = sizeof(primes) / sizeof(primes[0]) };
/*
** In the context of next_prime_after(), this function is never called
** upon to validate small numbers - numbers less than primes[N_PRIMES-1]
** are not passed here. In more general contexts, the extra conditions
** in the conditionally compiled code are necessary for accuracy.
*/
static bool is_prime(unsigned p)
{
for (int i = 0; i < N_PRIMES; i++)
{
#ifndef NEXT_PRIME_AFTER
if (p < primes[i])
return false;
if (p == primes[i])
return true;
#endif /* NEXT_PRIME_AFTER */
if (p % primes[i] == 0)
return false;
}
for (unsigned t = primes[N_PRIMES - 1]; t * t <= p; t += 6)
{
if (p % t == 0)
return false;
if (p % (t + 2) == 0)
return false;
}
return true;
}
static unsigned next_prime_after(unsigned start)
{
for (int i = 0; i < N_PRIMES; i++)
{
if (start < primes[i])
return primes[i];
}
for (unsigned x = (start + 1) / 6; x < UINT_MAX / 6; x++)
{
unsigned t = 6 * x - 1;
if (t > start && is_prime(t))
return(t);
t += 2;
if (t > start && is_prime(t))
return(t);
}
return 0;
}
int main(void)
{
assert((primes[N_PRIMES-1]+1) % 6 == 0);
for (unsigned u = 0; u < 100; u++)
printf("%3u => %3u\n", u, next_prime_after(u));
for (unsigned t = 100, u = next_prime_after(t); u < 12345678; t = u)
printf("%3u => %3u\n", t, (u = next_prime_after(t)));
}
请注意此处的isprime()
函数。它是针对这种情况而量身定制的,并省略了通用独立测试仪所需的检查。 next_prime_after()
逐步遍历已知素数的列表(如果您可能要处理许多可能的素数,则可以添加测试以查看是否值得完全经历第一个循环),然后逐步执行6N±1序列以寻找素数。
测试代码在从0到99的每个数字之后打印下一个素数。此后,它将逐步遍历素数,直到12345701(这是12345678之后的第一个素数)。
0 => 2
1 => 2
2 => 3
3 => 5
4 => 5
5 => 7
6 => 7
7 => 11
8 => 11
9 => 11
10 => 11
11 => 13
12 => 13
13 => 17
14 => 17
15 => 17
16 => 17
17 => 19
18 => 19
19 => 23
20 => 23
21 => 23
22 => 23
23 => 29
…
95 => 97
96 => 97
97 => 101
98 => 101
99 => 101
100 => 101
101 => 103
103 => 107
107 => 109
109 => 113
113 => 127
127 => 131
…
12345581 => 12345623
12345623 => 12345637
12345637 => 12345643
12345643 => 12345647
12345647 => 12345653
12345653 => 12345701