【问题标题】:Numbers 3, 5, and 7 not being displayed as prime数字 3、5 和 7 未显示为素数
【发布时间】:2013-10-09 00:03:16
【问题描述】:

我需要创建一个在两个输入数字之间生成素数的函数。我通过测试范围内每个数字的素数来做到这一点。问题是数字 3、5 或 7 从不显示。我不确定出了什么问题。

这就是我测试数字素数的方法:

bool isPrime(int number){
    using namespace std;
    if((number%2==0) || (number%3==0) || (number%4==0) || (number%5==0) ||
       (number%6==0) || (number%7==0) || (number%8==0) || (number%9==0))
    {
        return false;
    }
    else if ((number/1==number) && (number/number==1))
    {
        return true;
    }
}

【问题讨论】:

  • 我可以马上告诉你,这不是找到素数的正确代码
  • 您的代码几乎等同于仅列出您范围内的所有素数并检查输入是否是其中之一。不要偷懒,请创建一个实际的素性测试。另外,(number/1==number) && (number/number==1) 毫无意义。
  • 简单。因为3 % 30,并且由于条件中有(number%3==0),所以该函数的输出是false
  • 您是否在两个输入数字之间的每个数字上调用 isPrime?即便如此,即使 3 是素数,isPrime(3) 也会返回 false...
  • isPrime(2) 也会返回 false,即使 2 是素数。所以不只是 3、5 和 7。

标签: c++ algorithm math primes


【解决方案1】:

3 是 3 的倍数。5 是 5 的倍数。7 是 7 的倍数。您编写的代码对 3、5 或 7 的任何倍数都返回 false,因此它不可能返回 true那些数字。您只需要检查小于您要检查的数字的素数是否可整除。

您还检查了许多不必要的合数的整除性;例如,一个数字不能是 4 的倍数而不是 2 的倍数,也不能是 6 的倍数而不是 2 的倍数 3。这些检查什么都不做除了浪费时间。

最后,从长远来看,您的代码 100% 的时间都是错误的,因为它检查的最高质数是 7。它会说 169 (13 * 13) 是质数,因为它不能被任何你检查的数字,但它显然是复合的。对于试除法,您需要检查 所有 小于或等于 floor(sqrt(n)) 的素数,方法是对复合材料进行大量不必要的检查,或者建立一个素数列表随你去(类似于埃拉托色尼筛,经常被 CS 类型称为,但我不认为它是严格等价的)。

【讨论】:

  • 在数学上,您只需要检查所有小于您正在检查的数字的(四舍五入)平方根的数字。如果在那之前没有任何东西是倍数,那么之后也没有任何东西。
  • @ZacHowland 是的,我会修改的。
  • 如果它是“100% 错误”,您就不必用“从长远来看”来限定它。该代码将为 10 到 120 之间的数字生成 100% 正确的结果,包括 10 到 120。
  • @WillNess 我的意思是非常具体的。渐近地它是正确的 0% 的时间。
【解决方案2】:

一个非常简单(但不是那么有效)的方法:

bool is_prime(int i)
{
    int root = (int)std::sqrt(i);
    bool result = true;
    for (int j = 2; j <= root; ++j)
    {
        if (i % j == 0)
        {
            result = false;
            break;
        }
    }
    return result;
}

【讨论】:

  • result=false; break; 风格不好。您应该立即返回,不要为可能的错误介绍留下任何空间。
  • @WillNess 对于这样一个简单的功能,这可能是可以接受的;然而,对于一个较大的函数,其返回值分散在整个函数中,这使得重构、调试和维护变得困难。
【解决方案3】:

您可能想看看this 文章。

这是一种寻找素数的系统方法。使用此算法不断寻找素数,直到达到输入的上限值。

【讨论】:

    【解决方案4】:

    看这行代码:

    if((number%2==0) || (number%3==0) || 
       (number%4==0) || (number%5==0) ||
       (number%6==0) || (number%7==0) ||
       (number%8==0) || (number%9==0))
       return false;
    

    想想如果你插入 2、3、5 或 7 会发生什么。在每种情况下,你会发现数模 2、模 3、模 5 或模 7 确实为零,所以你的代码将返回 false。这可能解释了为什么你得到的这些数字不算作素数。

    但现在看下一条语句:

    else if ((number/1==number) && (number/number==1)){
        return true;
    }
    

    在什么情况下这是错误的?每个数字除以一就是它本身,每个数字除以它本身就是一,所以 每个 数字都通过了这个测试。因此,只要它不能被 2、3、4、5、6、7、8 或 9 整除,您的代码将对任何数字返回 true。尝试插入 11 x 13 = 143。这个数字不是t prime,但你的函数会说它是。

    其他人已经发布了您可以采取的其他途径来解决问题,但从根本上说,我认为问题是如果 no 数字不是 1 并且它本身是除数,则该数字是素数。您的函数将需要以某种方式解决这一问题,可能通过检查它下面的所有不是一个或本身的数字。正如一些答案所建议的那样,可以进一步优化这一点,但您应该知道,在基本层面上,这是需要做的。

    希望这会有所帮助!

    【讨论】:

      【解决方案5】:

      或者你可以使用这个算法:

      #include<iostream>
      #include<string>
      #include<cmath>
      
      using namespace std;
      
      int main()
      {
          int num;
          int count = 0;
      
          cout << "Enter your range: ";
          cin >> num;
      
          for(int i = 1; i <= num; i++)
          {
              count = 0;
              for(int j = 2; j <= sqrt(i); j++)
              {
                  if(i % j == 0)
                  {
                      count++;
                      break;
                  }
              }
              if(count == 0 && i != 1)
                  cout << i << "   ";
          }
          cout << endl;   
      }
      

      【讨论】:

      • 1.反复计算 sqrt 很糟糕。 2.使用计数也不好。如果 int n >= 2 的除数介于 2 和 sqrt(n) 之间,那么您可以立即得出结论,它不是素数
      猜你喜欢
      • 2014-10-05
      • 2017-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-25
      • 1970-01-01
      • 2013-01-07
      相关资源
      最近更新 更多