【问题标题】:Weird situation in prime number checking code素数校验码的奇怪情况
【发布时间】:2016-04-30 15:45:45
【问题描述】:

当我为 Project Euler 解决问题时,它要求我总结所有低于 200 万的素数。这是我的代码:

#include<stdio.h>
#include<math.h>
int isPrime(int);
int main() {
    long long int sum = 0;
    int i; // index
    for(i = 2 ; i < 2000000 ; i++) {
        if(isPrime(i)) {
            sum += i;
        }
    }
    printf("%lli\n", sum);
}

int isPrime(int num) {
    int i; // index
    int sq = sqrt(num);
    for(i = 2 ; i <= sq ; i++) {
        if(num % i == 0) {
            return 0;
        }
    }
    return 1;
}

此代码导致正确答案 142913828922。 但是当我将isPrime() 中的 for 循环更改为:

for(i = 2; i <= sq+1; i++)   // or even sq+2, sq+3, etc.

导致142913828920和142913828917等不正确的结果

为什么会出错?从理论上讲,它不会改变isPrime() 发送到main() 的号码,是吗?

【问题讨论】:

  • 可能你使用的数字太大

标签: c algorithm primes


【解决方案1】:

如果您将循环更改为

for(i = 2 ; i <= sq+1 ; i++)

那么 2 不再被认为是素数,因为你测试了 2 % 2 == 0

对于您添加的较大数字类似,越来越多的素数将不会被检测到。

【讨论】:

    【解决方案2】:

    考虑到您将总和从142913828922 更改为142913828920,那么差值是2,这意味着您将2 解释为非质数。将 sq 更改为 sq+1 应该可以实现这种差异。将其更改为 sq+2 最终会使 3 不是素数。

    ((int)sqrt(2))+1 == 2
    ((int)sqrt(3))+2 == 3
    

    等等。

    【讨论】:

    • 非常感谢!!逻辑陷阱现在似乎没有那么棘手了。
    【解决方案3】:

    最好用

    for(i = 2 ; i*i <= num ; i++) {
        if(num % i == 0) {
            return 0;
        }
    }
    

    代替

    int sq = sqrt(num);
    for(i = 2 ; i <= sq ; i++) {
        if(num % i == 0) {
            return 0;
        }
    }
    

    用 sqrt 函数避免这个问题

    【讨论】:

      猜你喜欢
      • 2015-04-04
      • 1970-01-01
      • 2021-06-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-06
      • 2010-12-30
      • 1970-01-01
      相关资源
      最近更新 更多