[英]C++ Prime Numbers from 3 to n
I wrote this code to print all prime numbers between 3 and 'n' inputted by the user, but upon running, it produces nothing.我编写了这段代码来打印用户输入的 3 到 'n' 之间的所有素数,但是在运行时,它什么也没产生。
Can you please help?你能帮忙吗?
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
for (int candidate = 3; candidate < n; ++candidate)
{
bool isPrime = true;
for (int x = 2; x < n; x++)
{
if (candidate % x == 0)
{
isPrime = false;
}
}
if (isPrime)
{
cout << n << "";
}
}
}
One thing you should know.你应该知道的一件事。 For checking whether n is prime if we start checking by division operation then you shouldn't check more than
sqrt(n)
.如果我们开始通过除法运算来检查 n 是否为素数,那么检查的次数不应超过
sqrt(n)
。
for (int candidate = 3; candidate < n; ++candidate)
{
bool isPrime = true;
for (int x = 2; x*x < candidate; x++)
{
if (candidate % x == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
cout << candidate << "";
}
}
isPrime: initialize with all true
for(int i=2;i*i<=n;i++)
for(int j =i*i;j<=n;j+=i)
isPrime[j]=false; // the if was not needed.
Now you know which are primes between 3 and n
.现在您知道哪些是 3 和
n
之间的素数。
There are several efficiency savings possible in your code.在您的代码中可以节省一些效率。 The most efficient method (apart from using a pre-calculated look-up table for small (<1000)
n
) is the sieve of Erastosthenes .最有效的方法(除了对小 (<1000)
n
使用预先计算的查找表)是Erastosthenes的筛法。
A very naive version of this algorithm (see also the answer by coderredoc )该算法的一个非常幼稚的版本(另请参阅coderredoc的答案)
std::vector<int> primes(int n)
{
std::vector<bool> is_prime(n+1,true);
for(auto divisor=2; divisor*divisor <= n; ++divisor)
for(auto candidate=divisor*divisor; candidate <= n; candidate+=divisor)
is_prime[candidate]=false;
std::vector<int> result;
for(auto candidate=2; candidate <= n; ++candidate)
if(is_prime[candidate]) result.push_back(candidate);
return result;
}
essentially reverses the loops over candidate
s and divisor
s compared to your original algorithm, but only tests for divisor
s satisfying divisor*divisor<=candidate
.与您的原始算法相比,本质上反转了
candidate
s 和divisor
s 上的循环,但仅测试满足divisor*divisor<=candidate
divisor
s。
This algorithm can be substantially improved by realizing that we only need to test for prime divisors (which is the main trick of the sieve)通过意识到我们只需要测试素数除数(这是筛法的主要技巧),可以大大改进该算法
std::vector<int> primes(int n)
{
std::vector<bool> is_prime(n+1,true);
for(auto divisor=2; divisor*divisor <= n; ++divisor)
if(is_prime[divisor])
for(auto candidate=divisor*divisor; candidate <= n; candidate+=divisor)
is_prime[candidate]=false;
std::vector<int> result;
for(auto candidate=2; candidate <= n; ++candidate)
if(is_prime[candidate]) result.push_back(candidate);
return result;
}
which cuts down on the testing for large n
.这减少了对大
n
的测试。 A further efficiency saving (by a factor ~2 in space and time) is possible by avoiding even candidate
s and divisor
s:通过避免偶数
candidate
s 和divisor
s,可以进一步提高效率(空间和时间上的约 2 倍):
std::vector<int> primes(int n)
{
if(n<2) return {};
if(n==2) return {2};
std::vector<bool> is_prime((n+1)>>1,true);
for(auto divisor=3; divisor*divisor <= n; divisor+=2)
if(is_prime[divisor>>1])
for(auto candidate=divisor*divisor; candidate <= n; candidate+=2*divisor)
is_prime[candidate>>1]=false;
std::vector<int> result(1,2);
for(auto candidate=3; candidate <= n; candidate+=2)
if(is_prime[candidate>>1]) result.push_back(candidate);
return result;
}
This algorithm has a poor memory access pattern (into the is_prime[]
), which becomes a problem for very large n
.该算法具有较差的内存访问模式(进入
is_prime[]
),这对于非常大的n
成为一个问题。 A more sophisticated method, segmented sieve , can avoid that, see the above link.一种更复杂的方法,分段筛,可以避免这种情况,请参阅上面的链接。
Change your inner loop from改变你的内循环
for (int x = 2; x < n; x++)
{
if (candidate % x == 0)
{
isPrime = false;
}
}
to到
for (int x = 2; x < candidate; x++)
{
if (candidate % x == 0)
{
isPrime = false;
break;
}
}
otherwise x
would eventually become candidate
itself and candidate%candidate
is 0
which would cause isPrime
to become false
.否则
x
最终将成为candidate
本身,而candidate%candidate
为0
,这将导致isPrime
变为false
。
The break
statement is used because after being sure that the number is not prime, there's no need of further iterations.使用
break
语句是因为在确定数字不是素数之后,就不需要进一步的迭代了。
And since you consider only numbers from 3
, you could change your outer loop to save some iterations like而且由于您只考虑
3
数字,因此您可以更改外循环以保存一些迭代,例如
for (int candidate = 3; candidate < n; candidate+=2)
This would increment candidate
by 2
each time.这将使
candidate
每次增加2
。 This is okay because no even numbers greater than 2 are not prime.这是可以的,因为没有大于 2 的偶数不是素数。
Also, if the range of numbers you are considering is inclusive of n
, you may modify the outer for loop to此外,如果您考虑的数字范围包含
n
,您可以将外部 for 循环修改为
for (int candidate = 3; candidate < n; candidate+=2)
to consider n
as well.还要考虑
n
。
It's not recommended to use using namespace std;不推荐使用 using namespace std; — because this imports all of the identifiers from std.
— 因为这会从 std 中导入所有标识符。 See this question on Stack Overflow .
请参阅Stack Overflow上的这个问题。
Should the end condition of the second loop be candidate
instead of n
, ie第二个循环的结束条件是否应该是
candidate
而不是n
,即
for (int x = 2; x < candidate; x++)//not before N prime numbers divine up to them { if (candidate % x == 0) isPrime = false; }
Shouldn't you put out candidate
instead of n
你不应该推出
candidate
而不是n
I think this should work我认为这应该有效
#include <iostream>
#include <vector>
int main()
{
//setup start parameters
//test sequence
std::vector<int> test_sequence {2};
int end_number, start_number;
start_number = 3;
//take wished end number
std::cin >> end_number;
// test is wished number smaler than start number
if (start_number < end_number)
{
// loop which goes trough every number between start and end number
for (start_number; start_number <= end_number; start_number++)
{
bool isPrime = true;
//test is this number prime
for (int n = 0; n < test_sequence.size(); n++)
{
if (start_number % test_sequence[n] == 0 && start_number != test_sequence[n] )
{
isPrime = false;
}
}
if (isPrime)
{
std::cout << start_number << std::endl;
//hold result for next test
test_sequence.push_back(start_number);
}
}
}
else
{
std::cout << "Wrong input";
}
}
Result for first 200前 200 名的结果
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.