【问题标题】:C++ code for checking for prime numbers not working用于检查素数的 C++ 代码不起作用
【发布时间】:2012-08-01 06:41:01
【问题描述】:

我在处理这个 C++ 代码时遇到了问题。整数num 是一个我想检查它是否为素数的数字。然而,这个程序总是返回 false。这可能很简单,但我找不到任何东西。

for(int i=2;i<num;i++){ //primes are allowed to be divided by 1 so we start at 2
        if(num % i == 0){ //can be divided by a number other than itself or 1 so we trip out
            return false;
        } else if(i == num){ //if we've already done checks as high as possible and not tripped out yet then report success
            return true;
        }
}

【问题讨论】:

    标签: c++ primes


    【解决方案1】:

    i == num 永远不会发生,因为您的循环条件是i&lt;num。试试:

    for(int i=2;i<num;i++){ //primes are allowed to be divided by 1 so we start at 2
        if(num % i == 0){ //can be divided by a number other than itself or 1 so we trip out
            return false;
        } else if(i == num-1){ //if we've already done checks as high as possible and not tripped out yet then report success
            return true;
        }
    }
    

    如下所述,这里的else条件是多余的,你只需要从2到sqrt(num)检查——因为剩下的因素已经检查过了。

    根据您想要解决问题的复杂程度,可以进行更多改进。现实中的大多数方法都使用概率算法。

    【讨论】:

    • for(i==2;i
    • 我什至建议for(i==2;i*i&lt;=num;i++){if(num%i==0) return false} return true;
    • 正确的最大值是 const int maxvalue = static_cast(sqrt(num));
    • 每个人似乎都在用多次返回、中断等不必要地复杂化事情。为什么不只是简单地:int limit = sqrt(num); int i = 3; while ( i &lt;= limit &amp;&amp; num % i != 0 ) i += 2; return i &lt;= limit;(当然是对偶数的初始测试)。
    • @Axel 我没有看到更多代码,也没有更多条件。并且有几种既定的复杂性衡量标准。 (如果您按照我的建议进行操作,还有更多代码:首先检查偶数,然后从 3 开始迭代,步长为 2。但无论如何,这是您可能想要做的优化。)
    【解决方案2】:

    您不必检查每个数字,因为其中很多很容易被排除。例如,在检查num 不能被2 整除后,您可以跳过所有其他偶数。这样可以节省一半的测试。

    我们也绝对知道任何其他因素必须小于num/2(或者实际上是sqrt(num),但这更难计算)。这些知识可以为我们节省另一半的测试。

    所以现在我们有:

    if (num % 2 == 0)
        return false;
    
    for(int i = 3; i < num / 2; i += 2){ 
         if(num % i == 0){ //can be divided by a number other than itself or 1 so we trip out
             return false;
         }
    }
    
    // arriving here we have found no factors, so it must be a prime
    return true;
    

    【讨论】:

    • "(或者真的是sqrt(num),但这更难计算)" 但是您在这句话中就有了代码。 ;-]
    • 既然你已经提到,计算 sqrt 真的超过从 srqt -> num/2 开始吗?由于计算 sqrt 的成本很高,我们停止在 sqrt 上不会获得任何优势吗?
    • 我只是在这里采摘一些低垂的果实,减少了 75% 的运行时间。我们所做的任何其他事情显然只会​​影响剩下的 25%——值得付出额外的努力吗?这取决于。
    • @MohanKumar 除非num 非常小,否则sqrt(num) 将明显少于num / 2,这意味着循环的次数要少得多。在现代机器上,sqrt(num) 也不应该很贵。
    • 在计算 num % i 时,某些硬件(如 x86)也会提供 num / i 作为副产品。我们可以将其用作不断缩小的上限。
    【解决方案3】:

    Will Ness 的代码的一个小优化,只计算for外数的sqrt。条件检查执行多次,每次都计算sqrt没有意义。

    if( num == 2 ) return true;
    if( num < 2 || num % 2 == 0 ) return false;
    int sqrt = sqrt(num);
    
    for( int i=3; i<=sqrt; i+=2 ){   
            if(num % i == 0){ 
                return false;
            } 
    }
    return true;
    

    到目前为止,我认为这是最有效的方法!

    【讨论】:

    • 我认为编译器会执行该优化。 :) 顺便说一句,我对代码进行了编辑,我认为它应该会快 30%。
    【解决方案4】:
    bool CheckPrime(int num) {
        bool yayornay = true;
        for(int i = 2; i < num; i++) {
             if(num % i == 0) {
                 yayornay = false;
                 break;
             }
        }
        return yayornay;
    }
    

    【讨论】:

    • 没有break?效率太低了。
    • @JeffSchweigler 你错过了 if 的括号。如果没有大括号,您的代码将在第一次迭代中中断。编辑以更正相同的内容。
    • 你说的是第四行吗?我故意省略了括号并将第五行设为内联,因此它不需要它们。 =)
    • 将多个语句放在同一行不会以某种方式将它们组合在一起。 @Mohan 是对的。
    【解决方案5】:
    bool isprime(int n)
    {
        if(n<2) return false;
        if(n==2)return true;
        for(int i=2;i<=sqrt(n);i++)
            if(n%i==0) return false;
        return true;
    }
    

    【讨论】:

    • 您的解决方案与@ZelterAdy 的解决方案非常相似。但是,他的算法比您的算法更有效。那么,您发布另一个不提供任何附加值的解决方案的原因是什么?
    【解决方案6】:

    下面是写出你的意思的正确方法:

    int i=2;                     // move declaration out
    for(/*int i=2*/;i<num;i++){ 
            if(num % i == 0){ 
                return false;
            } // else            // and the final test too
    }
    if(i == num){                
        return true;
    }
    

    但这不是有效的。您只需检查i 不超过sqrt(num)。另外,如果您检查num%2,则无需再检查任何其他偶数,因此您可以使用 2 的增量。或者您甚至可以按 6 计数:

    if( num == 2 || num == 3 ) return true;
    if( num < 2 || num % 2 == 0 || num % 3 == 0 ) return false;
    for( int i=5, j=7, lim=sqrt(num); i<=lim; i+=6, j+=6 ){   
            if( num % i == 0 || num % j == 0 ){ 
                return false;
            } 
    }
    return true;
    

    (注意:这比这里的另一个答案更有效,它说这是这个答案的初始版本的“优化”)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多