0

I'm wondering if there is something inefficient in this code I've made, or if there is a faster way to find prime numbers.

#include <stdio.h>

int main(void)
{
    int count;

    for(int i=3; i<1000; i+=2){//search number in range of 3~999
        count=0;//init count
        for(int j=3; j*j<=i; j+=2){
            if(count==1){//if i has aliquot already, break the loop
                break;
            }
            if(i%j==0){
                count=1;//if i has aliquot, change count to 1
            }
        }
        if(count==0){
            printf("%d ", i);//if there are no aliquot, print i
        }
    }

    return 0;
}
LGJ
  • 19
  • 2
  • 5
    I think that's one of the worst methods to find prime numbers. For something simple better start out with an implementation of the _Sieve of Erathostenes_ or a _Miller Rabin_ prime test. – πάντα ῥεῖ May 28 '22 at 07:29
  • 1
    Every prime number less than 1000 can be found by looking only at factors <32, that is up to sqrt(1000). – rossum May 28 '22 at 07:43
  • [here](https://godbolt.org/z/hWKrE1dTY)'s the most efficient way to print prims less than 1000. – n. m. could be an AI May 28 '22 at 07:45
  • There are only ~200 million primes from 1 to 4000000000 and you are using 32-bit integer so you could just precompute and get the result from LUT at RAM latency. – huseyin tugrul buyukisik May 28 '22 at 08:51
  • Primes less than 1000 can be found by the Miller Rabin prime test using just `2` as witness. Anything up to MAX_INT only needs 3 or 4 witnesses iirc. That's probably the fastest test if you only need a handfull of numbers tested. If you want to print them all or test millions then a sieve is the best. – Goswin von Brederlow May 28 '22 at 15:53
  • Just a note on naming, it would be better to have `bool is_prime = true; // initialise` rather than `int count = 0`. At first I thought you were counting the number of non-primes in the range of \[3, 1000). If an `int` can only take on 2 values, that's a good hint it ought to be a `bool`. [Here's an edited version of your code (same algorithm)](https://godbolt.org/z/9zfnhh998), note there's only one `if` in the loop. – Elliott May 29 '22 at 09:37
  • https://www.godbolt.org/z/3axbf1 – Marek R May 31 '22 at 11:17
  • Does this answer your question? [Which is the fastest algorithm to find prime numbers?](https://stackoverflow.com/questions/453793/which-is-the-fastest-algorithm-to-find-prime-numbers) – Saint-Martin Jun 01 '22 at 05:17

3 Answers3

3

Trial division is inefficient for finding all prime numbers in a range since it takes O(√n) time to determine the primality of a single number. To find all prime numbers in a range efficiently, consider using the sieve of Eratosthenes (with time complexity O(nlognloglogn)) or Euler's sieve (with time complexity O(n)).

Implementation for the sieve of Eratosthenes

bool isPrime[N];

void eratosthenes(int n) {
    for (int i = 2; i <= n; ++i) {
        isPrime[i] = true;
    }
    isPrime[1] = false;
    for (int i = 2; i * i <= n; ++i) {
        if (isPrime[i]) {
            for (int j = i * i; j <= n; j += i) {
                isPrime[j] = false;
            }
        }
    }
}

Implementation for Euler's sieve

bool isPrime[N];
std::vector<int> primes;

void euler(int n) {
    for (int i = 2; i <= n; ++i) {
        isPrime[i] = true;
    }
    isPrime[1] = false;
    for (int i = 2; i <= n; ++i) {
        if (isPrime[i]) primes.push_back(i);
        for (size_t j = 0; j < primes.size() && i * primes[j] <= n; ++j) {
            isPrime[i * primes[j]] = false;
            if (i % primes[j] == 0) break;
        }
    }
}
wtz
  • 426
  • 4
  • 15
0

Eratosthenes Sieve is cool, but deprecated ? Why not use my Prime class ? it has an incrementation method, does not not use division. Prime class describes a number through its congruences to lower primes. Incrementing a prime is to increase all congruences, a new congruence is created if the integer is prime (all congruences -modulos_- differ from 0).

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>

class Prime {
public :
  Prime () : n_ (2), modulos_ (std::vector<std::pair<int, int> > ())
  {
    if (!modulos_.capacity ()) modulos_.reserve (100000000);
    std::pair<int, int> p (2, 0);
    modulos_.push_back (p);
  }
  ~Prime () {}
  Prime (const Prime& i) : n_ (i.n_), modulos_ (i.modulos_)
   {}
  bool operator == (const Prime& n) const {
    return (n_ == n.n_);
  }
  bool operator != (const Prime& n) const {
    return !operator == (n);
  }
  Prime& operator = (const Prime& i) {
    n_ = i.n_,
    modulos_ = i.modulos_;
    return *this;
  }
  void write (std::ostream& os) const {
    os << n_;
  }
  void operator ++ () {
    int prime (1);
    do {
      ++n_;
      prime = 1;
      std::for_each (modulos_.begin (), modulos_.end (), [&prime] (std::pair<int, int>& p) {
        ++p.second;
        if (p.first == p.second) {
          p.second = 0;
          prime  = 0;
        }
      });
    }
    while (!prime);
    std::pair<int, int> p (n_, 0);
    modulos_.push_back (p);
  }
  bool operator < (const int& s) const {
    return n_ < s;
  }
private :
  int n_;
  std::vector<std::pair<int, int> > modulos_; 
};

Usage :

int main (int, char**) {
  Prime p;
  do {
    p.write (std::cout);
    std::cout << std::endl;
    ++p;
  }
  while (p < 20);
}

Results : 2 3 5 7 11 13 17 19

Saint-Martin
  • 306
  • 3
  • 16
0

For the primes up to 1000, an efficient method is

cout << "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  101 103 107 109
113 127 131 137 139 149 151 157 163 167
173 179 181 191 193 197 199 211 223 227
229 233 239 241 251 257 263 269 271 277
281 283 293 307 311 313 317 331 337 347
349 353 359 367 373 379 383 389 397 401
409 419 421 431 433 439 443 449 457 461
463 467 479 487 491 499 503 509 521 523
541 547 557 563 569 571 577 587 593 599
601 607 613 617 619 631 641 643 647 653
659 661 673 677 683 691 701 709 719 727
733 739 743 751 757 761 769 773 787 797
809 811 821 823 827 829 839 853 857 859
863 877 881 883 887 907 911 919 929 937
941 947 953 967 971 977 983 991 997" << endl;