我的教授要求我做一个程序来测试哥德巴赫猜想。我想知道是否应该将 1 视为素数。这是我的代码,打印素数的第一个组合:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int n, i, j, k, l;
char prime, prime1;
do //check if n is even and greater than 2
{
printf("Give me an even natural number greater than 2:\n\n>");
scanf("%d", &n);
}
while (n % 2 != 0 && n >= 2);
for (i = 1; i < n ; i++)
{
prime = 1;
for (k = 2; k < i; k++)
if (i % k == 0)
prime = 0;
if (prime)
{
for (j = 1; j < n; j++)
{
prime1 = 1;
for (l = 2; l < j; l++)
if (j % l == 0)
prime1 = 0;
if (prime1)
if (i + j == n)
{
printf("\n\n%d and %d are the first two prime numbers that add up to %d.\n", i, j, n);
return 0;
}
}
}
}
}
我查了网上,几乎每个人都说1不是素数。我应该怎么办?保持程序原样还是更改它以使其不将 1 视为素数?我该怎么做? :P
您可以像哥德巴赫那样将
1
视为素数,也可以不像更常见的用法那样考虑,这对于猜想几乎没有区别。
将
1
视为质数具有以下效果:
2
有一个解决方案:1 + 1
。4
的第一对是1 + 3
而不是2 + 2
1
,但没有已知的大于2的偶数只能表示为p + 1
。请注意您的代码中存在问题:
您没有检查
scanf()
的返回值,因此输入不是数字的字符串将导致未定义的行为(第一次因为n
未初始化)或无限循环,因为n
不再被修改.测试
while (n % 2 != 0 && n >= 2);
不正确:应该是:
while (n <= 2 || n % 2 != 0);
第一个循环可以通过测试迭代一半的时间
i <= n / 2
第二个循环可以通过测试进行更少的迭代
k * k <= i
当你检测到
i
不是质数不需要第三次循环,你只需要测试
n - i
是否是素数第二个主要测试也可以进行相同的改进,最好将其移至单独的功能。
您应该收到一条消息和
return
声明,说明您极有可能找到哥德巴赫猜想的反例;-)这是一个改进版本:
#include <stdio.h>
#define PRIME_MASK ((1ULL << 2) | (1ULL << 3) | (1ULL << 5) | (1ULL << 7) |\
(1ULL << 11) | (1ULL << 13) | (1ULL << 17) | (1ULL << 19) | \
(1ULL << 23) | (1ULL << 29) | (1ULL << 31) | (1ULL << 37) | \
(1ULL << 41) | (1ULL << 43) | (1ULL << 47) | (1ULL << 53) | \
(1ULL << 59) | (1ULL << 61))
int isprime(unsigned long long n) {
if (n <= 63)
return (PRIME_MASK >> n) & 1;
if (n % 2 == 0)
return 0;
for (unsigned long long k = 3; k * k <= n; k += 2) {
if (n % k == 0)
return 0;
}
return 1;
}
int main(void) {
unsigned long long n, i;
int r;
for (;;) {
printf("Give me an even natural number greater than 2:\n>");
r = scanf("%llu", &n);
if (r == 1) {
if (n % 2 == 0 && n > 2)
break;
} else
if (r == EOF) { /* premature end of file */
return 1;
} else {
scanf("%*[^\n]%*c"); /* flush pending line */
}
}
#ifdef ONE_IS_PRIME
i = 1; /* start this loop at 1 if you want to assume 1 is prime */
#else
i = (n == 4) ? 2 : 3;
#endif
for (; i <= n / 2; i += 2) {
if (isprime(i) && isprime(n - i)) {
printf("%llu = %llu + %llu\n", n, i, n - i);
return 0;
}
}
printf("Goldbach was wrong!\n"
" %llu cannot be written as the sum of two primes\n", n);
return 0;
}
你可以认为1是素数,因为哥德巴赫在给莱昂哈德·欧拉的信中也认为1是素数。但那是1被认为是素数的时候。后来它被放弃了,因此这是哥德巴赫的第三次修正猜想另外,由于今天我们认为 1 既不是素数也不是合数,即使你不认为 1 是素数,这个猜想仍然成立,得到了很好的验证4*10^18(重新验证最多4*10^17)。
就你和教授打交道而言,你最好问他想要什么。
我添加了 is_prime 测试。 这更容易阅读。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
// gcc -o test gold_test.c -lm
bool is_prime(long n) {
if (n <= 3) return n > 1;
if ((n%6 != 1) && (n%6 != 5)) return false;
long limit = sqrt(n);
for (long i = 5; i<=limit; i+=6)
if (n%i == 0 || n%(i+2) == 0) return false;
return true;
}
int main()
{
long n, i, j, k, l;
do //check if n is even and greater than 2
{
printf("Give me an even natural number greater than 2:\n\n>");
scanf("%ld", &n);
}
while (n % 2 != 0 || n < 4);
if (n==4)
printf("\n\n%ld and %ld are the first two prime numbers that add up to %ld.\n", 2L, 2L, n);
else
for (i = 3; i <= n/2; i+=2)
{
if (is_prime(n-i) && is_prime(i)) {
printf("\n\n%ld and %ld are the first two prime numbers that add up to %ld.\n", i, n-i, n);
return 0;
}
}
}