Two issues my loops

Having two issues with this code. First, I need it to display the last 20 prime numbers. Currently it shows me the first 20 (this is probably an easy fix but I'm stumped at the moment). Secondly, the program is displaying 25 numbers instead of just 20 and I have no clue why. Any help would be greatly appreciated!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  #include <sstream>
#include <iomanip>
#include <cmath>
#include <iostream>
#include <fstream>
using namespace std;

    // Checks if prime
bool isPrime(int value){
    if (value == 2) 
        return true;
    for (int i = 2; i * i <= value; i++) {
        if (value % i == 0)
            return false;
    }
return true;
}

    // function declarations
bool isPrime(int value);
string formatPrime(int sequence,int prime);

    //Main
int main()
{
   //Variables
int num,counter=0;
string str="";
ofstream dataOut;
  
    cout<<"Prime Number Finder"<<endl;
  while(true){
      while(true){
          cout<<"\nPlease enter an integer between 30 and 2000: ";
          cin>>num;
          if(num==0){
              cout<<"\nBye!"<<endl;
              exit(0);
          }
  
//Opening primes.txt
dataOut.open("primes.txt");
  if(num<30 || num>2000)
   cout<<"Invalid.Must be between 30 and 2000"<<endl;
   else
   break;
   }
      
   cout<<"The last 20 Prime Numbers are:"<<endl;
   dataOut<<"The last 20 Prime Numbers are:"<<endl;
   for(int i=2;i<=num;i++){
       if(isPrime(i)){
           counter++;
           str=formatPrime(counter,i);
           cout<<str;
           // Putting data in primes.txt
           dataOut<<str;
           if(counter==0)
           break;
       }
   }
   dataOut<<endl;
   }

// Closing primes.txt
dataOut.close(); //Idk why it won't execute but screw it.
    return 0;
}
string formatPrime(int sequence,int prime)
{
   stringstream ss;
   ss<<"Prime # "<<sequence<<" = "<<prime<<endl;
   return ss.str();
}
If you need the last 20, then you have to have the primes before you show any of them. That is, you have to store them until you know that you have the last 20.
Last edited on
And in that vein, a <vector> is ideal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <vector>

bool isPrime(int value){
    if (value == 2)
        return true;
    for (int i = 2; i * i <= value; i++) {
        if (value % i == 0)
            return false;
    }
    return true;
}

int main()
{
    std::vector<int> table;
    
    for(int i = 0; i < 1000; i++)
    {
        if(isPrime(i))
            table.push_back(i);
    }
    
    for(size_t i = table.size() - 20; i < table.size(); i++)
    {
        std::cout << 20 - table.size() + i << '\t' << table[i] << '\n';
    }
    
    return 0;
}
size_t i = table.size() - 20;

That needs refinement, because input can be 30 and there are less than 20 primes under 30.

(size_t is unsigned integer and if one stores negative value into it , the value is converted into pretty large positive value ...)
Without writing to a file, perhaps:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <vector>

constexpr size_t ToDisplay {20};
constexpr unsigned Low {30};
constexpr unsigned High {2000};

bool isPrime(unsigned value) {
	for (unsigned i {3}; i * i <= value; i += 2)
		if (value % i == 0)
			return false;

	return true;
}

int main() {
	std::cout << "Prime Number Finder\n";

	for (unsigned num {1}; num; ) {
		do {
			std::cout << "\nPlease enter an integer between " << Low << " and " << High << " (0 to exit) : ";
			std::cin >> num;

		} while ((num != 0 && (num < Low || num > High)) && (std::cout << "Number not in range\n"));

		if (num) {
			std::vector<unsigned> table {2};

			for (unsigned i {3}; i < num; i += 2)
				if (isPrime(i))
					table.push_back(i);

			for (auto it {table.size() > ToDisplay ? table.end() - ToDisplay : table.begin()}; it < table.end(); ++it)
				std::cout << table.size() - (table.end() - it) + 1 << '\t' << *it << '\n';
		}
	}
}



Prime Number Finder

Please enter an integer between 30 and 2000 (0 to exit) : 1500
220     1373
221     1381
222     1399
223     1409
224     1423
225     1427
226     1429
227     1433
228     1439
229     1447
230     1451
231     1453
232     1459
233     1471
234     1481
235     1483
236     1487
237     1489
238     1493
239     1499

Please enter an integer between 30 and 2000 (0 to exit) : 0

(size_t is unsigned integer and if one stores negative value into it , the value is converted into pretty large positive value ...)
And in that vein ...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <vector>

bool isPrime(int value)
{
    if(value < 2)
        return false;
    if (value == 2)
        return true;
    for (int i = 2; i * i <= value; i++)
    {
        if (value % i == 0)
            return false;
    }
    return true;
}

int main()
{
    std::vector<int> table;
    size_t last{20};
    
    for(int i = 0; i < 30; i++)
    {
        if(isPrime(i))
            table.push_back(i);
    }
    
    int count{0};
    
    size_t start{0};
    if(table.size() > last)
        start = table.size() - 20;
    
    for(size_t i = start; i < table.size(); i++)
    {
        count++;
        std::cout << count << '\t' << table[i] << '\n';
    }
    
    return 0;
}
Last edited on
Just playing.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <valarray>
#include <numeric>
using namespace std;

slice betterSlice( int low, int high, int stride ){ return slice( low, ( high - low ) / stride + 1, stride ); }

valarray<int> sieve( int N )
{
   valarray<int> A(1+N);
   iota( begin(A), end(A), 0 );   A[1] = 0;
                                         if ( N >= 4 ) A[ betterSlice(   4, N, 2   ) ] = 0;
   for ( int i = 3; i * i <= N; i += 2 ) if ( A[i]   ) A[ betterSlice( i*i, N, 2*i ) ] = 0;
   return A[A>0];
}

int main()
{
   int high = 2000, num = 20;
   auto primes = sieve( high );
   cout << "The last " << num << " primes before " << high << " are\n";
   for ( int i = num; i; i-- ) cout << primes[primes.size()-i] << '\n';
}


The last 20 primes before 2000 are
1861
1867
1871
1873
1877
1879
1889
1901
1907
1913
1931
1933
1949
1951
1973
1979
1987
1993
1997
1999
Last edited on
Sieve, obviously.

On introduction valarray was the moon from the sky, but then did an awkward silence follow. Your post shows the power of interface.

One could think of a stack-based approach too. Compute "only" the last 20 primes. Then show the stack.
Topic archived. No new replies allowed.