this code is supposed to iterate through all consecutive numbers from 2 to 100 and should print all the prime numbers. What I get is instead a long list of repeated prime numbers with non-prime numbers showing up occasionally in between.
I am not so sure how to fix this.
#include <iostream>
int main()
{
for (int i = 3; i <= 100; i++)
{
bool prime = true;
for (int n = 2; n < i / 2 + 1; n++)
{
if (i % n == 0)
{
prime = false;
break;
}
}
if (prime)
{
std::cout << i << ' ';
}
}
std::cout << '\n';
}
I can see that you pretty much rewrote the whole code from scratch.
I appreciate your help, but do you think there is a way to slightly change my code
in order to obtain your same outcome, without using booleans? If I am a way off the track and is not possible, I understand.
#include <iostream>
usingnamespace std;
int main()
{
for (int i = 2; i <= 100; i++) // 2 is prime as well!
{
bool isPrime = true; // until told otherwise ...
for (int n = 2; n < i; n++) // you could actually reduce this to n <= sqrt(i) if desired
{
if (i%n == 0)
{
isPrime = false; // you need to update this
break; // no need to check any more
}
}
if ( isPrime ) cout << i << endl; // you need that boolean to gauge primeness
}
}
Go through your first post's code, line by line. Notice the logic within the inner for loop. n begins at 2. You then check if i % 2 == 0 (i.e. "is i even"). If i is even, you return false. If it is not even, you print it.
Essentially, you're checking if the number is even, and printing it if it isn't. (And then printing every other number that it isn't divisible by.) Do you see how this is different than checking if it's prime?
With minimal changes to your original code:
- start i at 2 instead of 3
- Declare n inside the outer loop and use its value after the inner loop to tell if the number was prime.
As others have stated, your algorithm is very inefficient because you check many more factors than necessary.
Using GOTO is bad habit, I know. But in this dull case and the lack of C++ to tell which one of nested loops to iterate I can not resist to eliminate the flag in lastchance's suggestion.
1 2 3 4 5 6 7 8 9 10 11 12 13
#include <iostream>
usingnamespace std;
int main()
{
for (int i = 2; i <= 100; i++) // 2 is prime as well!
{
for (int n = 2; n < i; n++) // you could actually reduce this to n <= sqrt(i) if desired
if (i%n == 0) goto next_i;
cout << i << endl; // you need no boolean to gauge primeness
next_i:;
}
}
But please, do not use this much farther than up to 100.
Edit: corrected a comment.
Note: I code transparently the jump otherwise concealed in if (isPrime)
int main()
{
for (int i = 2; i <= 100; i++) // 2 is prime as well!
{
for (int n = 2; n < i; n++) // you could actually reduce this to n <= sqrt(i) if desired
{
if (i%n != 0)
{ cout << i << endl;
}
else
{ break;
}
}
}
}
Though I write it more expanded than required, goto wasn't necessary here
What if we take MikeStgtās code and simply replace the goto with a continue.
1 2 3 4 5 6 7 8 9 10 11 12 13
#include <iostream>
usingnamespace std;
int main()
{
for (int i = 2; i <= 100; i++) // 2 is prime as well!
{
for (int n = 2; n < i; n++){ // you could actually reduce this to n <= sqrt(i) if desired
if (i%n == 0){continue; }
cout << i << endl; // you need no boolean to gauge primeness
}
}
}
Nope. The continue continues the loop that it's in.
Try this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#include <iostream>
#include <string>
usingnamespace std;
int main(int argc, char **argv) {
int limit = 100;
if (argc == 2) limit = stoi(argv[1]);
if (limit < 2) return 0;
cout << 2 << ' ';
for (int n = 3; n <= limit; n += 2) {
int d = 3;
for ( ; d * d <= n && n % d; d += 2) ;
if (d * d > n) cout << n << ' ';
}
cout << '\n';
}
MikeStgt's solution would benefit from a language change that I've always thought would be helpful. The idea is to let you break (or continue) an outer loop by specifying the constructs that you want to break/continue from:
1 2 3 4 5 6 7 8 9 10 11 12
#include <iostream>
usingnamespace std;
int main()
{
for (int i = 2; i <= 100; i++) // 2 is prime as well!
{
for (int n = 2; n < i; n++) // you could actually reduce this to n <= sqrt(i) if desired
if (i%n == 0) continueforfor; // continue not the inner for loop, but the outer one
cout << i << endl; // you need no boolean to gauge primeness
}
}
More specifically, break and continue could be followed by 1 or more for, do, or while keywords (or switch in the case of break). The keywords tell the compiler which construct the break/continue applies to by listing them from inner to outer.
This has the added advantage of helping to ensure that you're breaking/continuing the right structure. Beginners sometimes put a break inside a switch, thinking it will break out of an enclosing for loop.
If no keyword follows the break/continue then the behavior is the same as today (break/continue the inner most construct).
MikeStgt's solution would benefit from a language change that I've always thought would be helpful.
Would be helpful? It definitely is of great help. I know it from REXX with its loop changer iterate [name] and leave [name]. The [optional] name specifies which one of nestet loops is concerned. To implement this in C++ loops should be identifiable by name or other methods (the loop-determing variable for example as in REXX -- but for loops in C++ are so much "vicissitudinous", or variable?).
So nested-loops-aware break and continue in C++2059 earliest.