我的程序应该检测从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;
}
答案 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 :解决我们得到的错误:
使用修复并简化我们:
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;
}