1

I wrote this code to show the primes between 1 and 100. The only condition is to do not use functions, whole code should be inline. I would ask if I can improve (optimize) it much more?

#include<iostream>

using namespace std;

int main() {

    int i=2,j=2;

    cout<<"Prime numbers between 1 and 100 are:"<<endl;
    cout<<"2"<<"\t";
    while(i!=100) {
        for(int j=2;j<i;j++) {
            if(i%j==0)
            break;

            if(j==i-1)
            cout<<i<<"\t";
        }

        i++;
    }

    cout<<endl;
    system("pause");
    return 0;
}
John Humphreys
  • 37,047
  • 37
  • 155
  • 255
Aan
  • 12,247
  • 36
  • 89
  • 150
  • "The only condition is to do not use functions, whole code should be inline." Why not write functions and then turn on compiler optimizations so they'll be inlined for you? Best of both worlds. – GManNickG Nov 28 '11 at 21:04
  • 7
    You only have to check until `j <= sqrt(i)`. – Paul Manta Nov 28 '11 at 21:05
  • And the usual: use a profiler to determine which part of your code is used the most and running the slowest. If you've optimized that as much as possible, the algorithm needs to change. Introduce concurrency (if possible and meaningful), and use better algorithms (if they exist). – GManNickG Nov 28 '11 at 21:06
  • 4
    You only have to check odd numbers. There are no primes (except 2) that are divisible by even numbers, so you can replace `j++` with `j=j+2` to cut the search time in half. – Marc B Nov 28 '11 at 21:08
  • 2
    if this is homework, please add the homework tag! – Muad'Dib Nov 28 '11 at 21:10
  • 1
    What does optimize mean in this context? – EvilTeach Nov 28 '11 at 21:14
  • @MarcB: Incrementing by two is a valid optimization. However, it will not cut search time in half. Since the first thing the inner loop does is to test for divisibility by two, it would have succeeded immediately and determined that the number is not prime. With odd numbers the inner loop may have to go as far as the square root of the number to determine primality. – Ferruccio Nov 29 '11 at 00:26
  • @Ferrucio: He suggests incrementing `j` by two. Which means division(not just primality) will only be tried with odd numbers, which will indeed cut the search time in half. – Kleist Nov 29 '11 at 22:24

9 Answers9

3
    for(int j=2;j<i;j++){

This one is not nice.

First of all, you only need to check for j <= sqrt(i), as for example 7 will never divide 12 without a rest.

Second, you should keep track of all previously found prime numbers; keep it in vector and only do this loop for it's contents and for that condition I wrote.

Griwes
  • 8,805
  • 2
  • 43
  • 70
3

You could optimise your existing code:

  • In the while loop you should have a step of 2, so that you do not test the even numbers.
  • In your for loop you should stop when you reach the square root of the number you are testing

You could use a different method:

On the Sieve of Erastoses just removing the numbers divisable by 2,3 and 5 would significantly reduce the number of times you need to test for primality.

Shiraz Bhaiji
  • 64,065
  • 34
  • 143
  • 252
3

Avoid using the square root function, and increment your divisor by 2. Also some tricky things in the i loop to increment your possible prime by 2. Inner loop doesn't even need to check divisibility by 2 since no even numbers will even be tested.

int i,j,sq;
int min;
for(sq = 2; sq <= 10; sq++)
{
  min = (sq-1)*(sq-1);
  min = min + (min+1)%2; //skip if it's even, so we always start on odd
  for(i = min; i < sq*sq; i+=2)
  {
    for(j = 3; j <= sq; j+=2)
    {
      if (i%j == 0)
        bad;
    }
  }
}

note that the sq loop doesn't add time because it shrinks the inner loops proportionately.

Jean-Bernard Pellerin
  • 12,556
  • 10
  • 57
  • 79
2

You are checking every number from 2 to 100. But since 2 is the only even prime number, you can skip every even number after 2. This goes for both i and j. So start i and j at 3, and increment them by 2.

#include<iostream>

using namespace std;

int main() {
    cout<<"Prime numbers between 1 and 100 are:"<<endl;
    cout<<"2"<<"\t";
    for (int i=3; i<100;i+=2) {
        // This loop stops either when j*j>i or when i is divisible by j.
        // The first condition means prime, the second, not prime.
        int j=3;
        for(;j*j<=i && i%j!=0; j+=2); // No loop body

        if (j*j>i) cout << i << "\t";
    }
    cout<<endl;
    return 0;
}

In addition to the trick mentioned above, I've added the condition j*j<=i which logically is the exact same as j<=sqrt(i). There's no need to compute the square root when you can do a simple multiplication.

Kleist
  • 7,785
  • 1
  • 26
  • 30
2

If you just want primes below 100, there's no need to write code to compute them. It's perhaps a stupid answer, but it solves your problem as stated efficiently and concisely.

int main() {
    cout << "Prime numbers are:" << endl << "2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97" << endl;
    return 0;
}
  • 2
    You're missing the point. The primes themselves are not the interesting part, the algorithm is. – Paul Manta Nov 28 '11 at 21:26
  • Do you have any solution for my [question](https://stackoverflow.com/questions/48839408/c-loop-unrolling-for-prime-numbers) too? – ar2015 Feb 18 '18 at 04:16
1

Depends which optimisation you're looking to do. Yours is as good as possible that I can see if you're optimising for space first, time second (well, close - as long as you listen to @Paul, it will be). If you reverse the priorities, the Sieve of Erastothenes is faster (but will take up 100 booleans of your memory).

Amadan
  • 191,408
  • 23
  • 240
  • 301
  • If you want to get really fancy with saving memory you can use 100 one bit bitfields, which will save a lot of memory. :) Btw, there is one thing he could do: he could stop at `j <= sqrt(i)`. – Paul Manta Nov 28 '11 at 21:08
  • :) Yeah, I corrected it already. Good catch. Bitfields are still booleans, conceptually :P and handling bitfields will slow you down, so if speed is your objective, you'll probably use 100 bytes. – Amadan Nov 28 '11 at 21:13
1

Two simple optimizations you could do:

cout << 2 << '\t';
for (int i = 3; i <= 100; ++i) {
    for (int j = 3, l = (int)sqrt(i); j <= l; j += 2) {
        if (i % j == 0) {
            cout << i << '\t';
            break;
        } 
} 

What I did:

Math:

  • Stop when j > sqrt(i), there's no need to go further than that. Note however that sqrt is an expensive function; for your small sample (from 1 to 100), it might (read, will surely) cost you more to use it.
  • Only check odd numbers; do j += 2 instead of incrementing j one by one

Micro-optimizations:

  • Use ++i instead of i++; the latter has a temporary variable in which it stores the original value of i; the former does not.
  • Print '\t' as a character not as a string "\t".

(These micro-optimizations are probably made automatically by the compiler anyway, but there's no harm in knowing about them.)

Paul Manta
  • 30,618
  • 31
  • 128
  • 208
0

The most efficient way to accomplish this is the Sieve of Eratosthenes. Here's an incremental version, specifically tailored to producing the primes up to 100, one by one (maximum up to 120, because 121 == 11 * 11).

int m3 = 9, m5 = 25, m7 = 49, i = 3;
printf("2 ");
for( ; i < 100; i += 2 )
{
    if( i != m3 && i != m5 && i != m7)
        printf("%d ", i);
    else
    {
        if( i == m3 ) m3 += 6;
        if( i == m5 ) m5 += 10;
        if( i == m7 ) m7 += 14;
    }
}
Will Ness
  • 70,110
  • 9
  • 98
  • 181
-1
/*** Return an array of primes from 2 to n. ***/
int[] function nPrimes(int n) {
   int primes[];  //memory allocation may be necessary depending upon language.
   int p = 0;
   bool prime;
   for (int i = 2; i <= n; i++) {
       prime = true;
       //use (j <= (int)sqrt(i)) instead of (j < i) for cost savings.
       for (int j = 2; j <= (int)sqrt(i); j++)  {
           if (i % j == 0) {
               prime = false;
               break;
           }
       }
       if (prime) {
           primes[p++] = i;
       }    
   }
   return primes;
}
  • Can you please provide a quick summary of your code. I see what it is doing, but it would help the wider audience to know what you did specifically. – kgdesouz Jun 21 '13 at 18:02