C ++ Prime数字程序无法识别3?

时间:2014-07-26 20:07:07

标签: c++

我的程序应该检测从1到100的素数并将它们保存到文件中。

出于某种原因,它不识别3,但错误地将3的倍数(27,33等)识别为素数。

代码如下......

/* This program will use a function determine if a number is prime.
When called this function will be used to determine all 
prime numbers from 1- 100 and save them to a file*/

#include<iostream>
#include<cmath>
#include<fstream>
using namespace std;


bool isPrime(int);// function prototype

int main()
{
    ofstream fout;
    fout.open("prime.txt");
    bool result;
    int num; // variable to hold integer number
    for (num = 1; num >= 1 && num <= 100; num++)
    {
        result =isPrime(num);
        if (result == true)
        {
            fout << num<< endl;
        }
        else 
        {
            cout << num << " is not prime." <<endl;
        }
    }

    fout.close();



    system("pause");
    return 0;
}



bool isPrime(int test)
{
    //define prime as a bool integer
    bool prime;

    // check for 2, a prime number that will not be caught by for loop algorithm
    if (test == 2) 
    {
        prime = true;
    }
    // eliminate all even numbers other than 2
    else if ( test%2 == 0)
    {
        prime = false;
    }
    // eliminate 0
    else if ( test == 0)
    {
        prime = false;
    }
    //eliminate 1, which is not prime or composite
    else if ( test == 1)
    {
        prime = false;
    }
    // if test is not yet determined, check using algorithm 
    // this algorithm returns the remainder of a number (test)
    // divided by an integer (i) in the range of i = 1
    // to i = sqrt(number) 
    else
    {
        for(int i = 1; i <= (sqrt(test));i++)
        {
            if (test%i == 0)
            {
                prime = false;


            }

            else if (test%i != 0)
            {
                prime = true;

            }
        }

    }


    if (prime == true)
    {
        cout << "The number " <<test << " is prime." <<endl;
    }


    return prime;

编辑代码修补:

        /* This program will use a function determine if a number is prime.
When called this function will be used to determine all 
prime numbers from 1- 100 and save them to a file*/

#include<iostream>
#include<cmath>
#include<fstream>
using namespace std;


bool isPrime(int);// function prototype

int main()
{
    ofstream fout;
    fout.open("prime.txt");
    bool result;
    int num; // variable to hold integer number
    for (num = 1; num >= 1 && num <= 100; num++)
    {
        result =isPrime(num);
        if (result == true)
        {
            fout << num<< endl;
        }
        else 
        {
            cout << num << " is not prime." <<endl;
        }
    }

    fout.close();



    system("pause");
    return 0;
}



bool isPrime(int test)
{
    //define prime as a bool integer
    bool prime;
    double sqrt_num = sqrt(test);

    //check for number 2 which algorithm wont catch, but is prime
    if (test ==2)
    {
        return true;
    }


    // check if even and return false
    else if ( test% 2 == 0)
    {
        return false;
    }


    //eliminate 1, which is not prime or composite, and 0.
    else if ( test == 0 || test == 1)
    {
        return false;
    }
    // if test is not yet determined, check using algorithm 
    // this algorithm returns the remainder of a number (test)
    // divided by an integer (i) in the range of i = 1
    // to i = sqrt(number) 
    else
    {
        for(int i = 3; i <= sqrt_num;i+=2)
        {
            if (test%i == 0)
            {
                return false;

            }

        }

    }

    return true;



}

3 个答案:

答案 0 :(得分:1)

代码中最大的错误是for-loop:

for(int i = 1; i <= (sqrt(test));i++)
{
    if (test%i == 0)
    {
        prime = false;
    }

    else if (test%i != 0)
    {
        prime = true;

    }
}

如果我们单步执行您的错误测试用例3和27,我们会看到3是这样的:

for (int i = 1; i <= 1; i++)
{
    if (3 % 1 == 0)
    {
        prime = false;
    }
    else if (3 % 1 != 0)
    {
        prime = true;
    }
}

循环将被计算一次,并返回结果(false)。原因是你的循环以1开头,因为每个数字都可以被1整除,每个只检查1的数字将始终是复合数。要解决这个问题,我们只需要从数字2开始。如果我们这样做,我们必须为&#34; prime&#34;设置初始值。因为否则我们会返回一个空值。我们的初始值将是真的,这意味着每个数字都是素数,直到证明为止,方便地,这正是我们的for循环所做的。

当您到达27的循环的最后一次迭代时发生第二个错误:

//i == 5
for (int i = 1; i <= 5; i++)
{
    if (27 % 5 == 0)
    {
        prime = false;
    }
    else if (27 % 5 != 0)
    {
        prime = true;
    }
}

因为最后一次迭代将prime设置为true,所以返回true,这显然是错误的。一个可能的解决方案是,如果遇到number % i == 0所持有的i,则退出循环,因为这意味着我们找到了所述数字的有效因子。

<强> TL; DR :解决我们得到的错误:

  • 从数字2开始,而不是一个,以摆脱角落案例3(以及2)
  • 如果找到有效因子,则数字肯定复合,我们将prime设置为false并退出循环,因为我们找到了结果。

使用修复并简化我们:

bool isPrime(int number)
{
    // special cases 0 and 1
    if (i == 0 || i == 1)
    {
        return false;
    }

    // else check from i = 2 to sqrt(number) if any of them divides the number
    // if yes, the number is not prime and it returns false.
    for (int i = 2; i <= sqrt(number); i++)
    {
        if (number % i == 0)
        {
            return false;
        }
    }
    // if the number is not 0 or 1 and has passed the loop, it must be prime,
    // hence we can return true    
    return true;
}

要做的小优化是检查它是否是偶数,如果不是仅仅用奇数测试除法。然后我们将替换for循环:

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

答案 1 :(得分:0)

(int)sqrt(3)1,每test%1将返回0,因为除以1没有余数。

一旦找到证明该号码不是素数的证据,就应该停止循环。如果你坚持下去,结果会产生误导。

注意:sqrt()是一项昂贵的功能。考虑将其结果保存在变量中,这样您就不必每次循环运行它。

答案 2 :(得分:0)

由于您使用i = 1开始循环,因此条件test%i == 0始终为真。

因此,您应该使用i = 2启动它,这样您就可以测试大于或等于4的数字。

此外,设置break后,您应该prime = false循环。

您必须单独测试3,因为2 > sqrt(3)


一些改进建议:

bool isPrime(int number)
{
    // Handle 0 and 1
    if (number < 2)
        return false;

    // Handle 2 and 3
    if (number < 4)
        return true;

    // Handle numbers that are not adjacent to a multiple of 6
    if (number%2==0 || number%3==0)
        return false;

    // Calculate once
    int root = (int)sqrt(number);

    // Check divisibility by numbers that are equal to -1(mod6)
    for (int i=5; i<=root; i+=6)
    {
        if (number%i == 0)
            return false;
    }

    // Check divisibility by numbers that are equal to +1(mod6)
    for (int i=7; i<=root; i+=6)
    {
        if (number%i == 0)
            return false;
    }

    return true;
}