【问题标题】:Goldbach conjecture exercise (c)哥德巴赫猜想练习(c)
【发布时间】:2013-11-10 15:17:43
【问题描述】:

我的教授让我做一个程序来测试哥德巴赫猜想。我想知道我是否应该将 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 是素数,则素数分解不是唯一的。
  • 对于二元哥德巴赫猜想:while (n % 2 != 0 || n &lt;= 2);,两次...?
  • 你的 do-while 循环是错误的。你必须要求 n

标签: c primes goldbach-conjecture


【解决方案1】:

您可以将1 视为素数,就像哥德巴赫所做的那样,或者不像更常见的用法那样,它对猜想几乎没有区别。

1 视为素数具有以下效果:

  • 2 有一个解决方案:1 + 1
  • 4 的第一对是 1 + 3 而不是 2 + 2
  • 如果值是质数加一,则更大偶数的第一个解决方案可能涉及 1,但没有大于 2 的已知偶数只能表示为 p + 1

注意你的代码有问题:

  • 你没有检查scanf()的返回值,所以输入不是数字的字符串会导致未定义的行为(第一次为n未初始化)或无限循环为n不再修改。

  • 测试while (n % 2 != 0 &amp;&amp; n &gt;= 2);不正确:应该是:

    while (n <= 2 || n % 2 != 0);
    
  • 第一个循环的迭代时间可以是测试的一半i &lt;= n / 2

  • 第二个循环可以通过测试减少迭代次数k * k &lt;= 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;
}

【讨论】:

    【解决方案2】:

    你可以认为 1 是素数,因为哥德巴赫在给 Leonhard Euler 的信中也认为它是素数。但那是 1 被认为是素数的时候。后来它被放弃了,因此这是哥德巴赫的第三个修改后的猜想。另外,由于今天我们认为 1 既不是素数也不是合数,即使你不认为 1 是素数,这个猜想仍然成立,被很好地验证到 4*10^18 (re-验证高达 4*10^17)。

    至于你和教授打交道,你最好问问他想要什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      相关资源
      最近更新 更多