Sieve of Eratosthenes algorithm

后端 未结 14 1182
一生所求
一生所求 2020-12-15 12:55

I am currently reading \"Programming: Principles and Practice Using C++\", in Chapter 4 there is an exercise in which:

I need to mak

相关标签:
14条回答
  • 2020-12-15 13:23

    Think of the sieve as a set.
    Go through the set in order. For each value in thesive remove all numbers that are divisable by it.

    #include <set>
    #include <algorithm>
    #include <iterator>
    #include <iostream>
    
    
    typedef std::set<int>   Sieve;
    
    int main()
    {
        static int const max = 100;
    
        Sieve   sieve;
    
        for(int loop=2;loop < max;++loop)
        {
            sieve.insert(loop);
        }
    
    
        // A set is ordered.
        // So going from beginning to end will give all the values in order.
        for(Sieve::iterator loop = sieve.begin();loop != sieve.end();++loop)
        {
            // prime is the next item in the set
            // It has not been deleted so it must be prime.
            int             prime   = *loop;
    
            // deleter will iterate over all the items from
            // here to the end of the sieve and remove any
            // that are divisable be this prime.
            Sieve::iterator deleter = loop;
            ++deleter;
    
            while(deleter != sieve.end())
            {
                if (((*deleter) % prime) == 0)
                {
                    // If it is exactly divasable then it is not a prime
                    // So delete it from the sieve. Note the use of post
                    // increment here. This increments deleter but returns
                    // the old value to be used in the erase method.
                    sieve.erase(deleter++);
                }
                else
                {
                    // Otherwise just increment the deleter.
                    ++deleter;
                }
            }
        }
    
        // This copies all the values left in the sieve to the output.
        // i.e. It prints all the primes.
        std::copy(sieve.begin(),sieve.end(),std::ostream_iterator<int>(std::cout,"\n"));
    
    }
    
    0 讨论(0)
  • 2020-12-15 13:23

    From Algorithms and Data Structures:

    void runEratosthenesSieve(int upperBound) {
          int upperBoundSquareRoot = (int)sqrt((double)upperBound);
          bool *isComposite = new bool[upperBound + 1];
          memset(isComposite, 0, sizeof(bool) * (upperBound + 1));
          for (int m = 2; m <= upperBoundSquareRoot; m++) {
                if (!isComposite[m]) {
                      cout << m << " ";
                      for (int k = m * m; k <= upperBound; k += m)
                            isComposite[k] = true;
                }
          }
          for (int m = upperBoundSquareRoot; m <= upperBound; m++)
                if (!isComposite[m])
                      cout << m << " ";
          delete [] isComposite;
    }
    
    0 讨论(0)
  • 2020-12-15 13:26

    Here is a classic method for doing this,

    int main()
    {
        int max = 500;
        vector<int> array(max); // vector of max numbers, initialized to default value 0
    
        for (int i = 2; i < array.size(); ++ i) // loop for rang of numbers from 2 to max
        {
            // initialize j as a composite number; increment in consecutive composite numbers
            for (int j = i * i; j < array.size(); j +=i)
                array[j] = 1;  // assign j to array[index] with value 1
        }
    
        for (int i = 2; i < array.size(); ++ i) // loop for rang of numbers from 2 to max
            if (array[i] == 0)  // array[index] with value 0 is a prime number
            cout << i << '\n';  // get array[index] with value 0
    
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-15 13:29

    Interestingly, nobody seems to have answered your question about the output problem. I don't see anything in the code that should effect the output depending on the value of max.

    For what it's worth, on my Mac, I get all the output. It's wrong of course, since the algorithm isn't correct, but I do get all the output. You don't mention what platform you're running on, which might be useful if you continue to have output problems.


    Here's a version of your code, minimally modified to follow the actual Sieve algorithm.

    #include <vector>
    #include <iostream>
    
    using namespace std;
    
    //finds prime numbers using Sieve of Eratosthenes algorithm
    vector<int> calc_primes(const int max);
    
    int main()
    {
        const int max = 100;
    
        vector<int> primes = calc_primes(max);
    
        for(int i = 0; i < primes.size(); i++)
        {
            if(primes[i] != 0)
                cout<<primes[i]<<endl;
        }
    
        return 0;
    }
    
    vector<int> calc_primes(const int max)
    {
        vector<int> primes;
    
        // fill vector with candidates
        for(int i = 2; i < max; i++)
        {
            primes.push_back(i);
        }
    
        // for each value in the vector...
        for(int i = 0; i < primes.size(); i++)
        {
            //get the value
            int v = primes[i];
    
            if (v!=0) {
                //remove all multiples of the value
                int x = i+v;
                while(x < primes.size()) {
                    primes[x]=0;
                    x = x+v;
                }
            }
        }
        return primes;
    }
    
    0 讨论(0)
  • 2020-12-15 13:29

    Here is a more efficient version for Sieve of Eratosthenes algorithm that I implemented.

    #include <iostream>
    #include <cmath>
    #include <set>
    
    using namespace std;
    
    void sieve(int n){
        set<int> primes;
        primes.insert(2);
        for(int i=3; i<=n ; i+=2){
            primes.insert(i);
        }       
    
        int p=*primes.begin();
        cout<<p<<"\n";
        primes.erase(p);
    
        int maxRoot = sqrt(*(primes.rbegin()));
    
        while(primes.size()>0){
            if(p>maxRoot){
                while(primes.size()>0){
                    p=*primes.begin();
                    cout<<p<<"\n";
                    primes.erase(p);        
                }
                break;
            }
    
            int i=p*p;  
            int temp = (*(primes.rbegin()));
            while(i<=temp){
                primes.erase(i);
                i+=p;
                i+=p;
            }
            p=*primes.begin();
            cout<<p<<"\n";
            primes.erase(p);
        }
    }
    
    int main(){
        int n;
        n = 1000000;
        sieve(n);                
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-15 13:30

    Here is a concise, well explained implementation using bool type:

    #include <iostream>
    #include <cmath>
    
    void find_primes(bool[], unsigned int);
    void print_primes(bool [], unsigned int);
    
    //=========================================================================
    int main() 
    {
        const unsigned int max = 100;
        bool sieve[max];
    
        find_primes(sieve, max);
    
        print_primes(sieve, max);
    }
    //=========================================================================
    
    /*
        Function: find_primes()
        Use: find_primes(bool_array, size_of_array);
    
        It marks all the prime numbers till the
        number: size_of_array, in the form of the
        indexes of the array with value: true.
    
        It implemenets the Sieve of Eratosthenes,
        consisted of:
    
        a loop through the first "sqrt(size_of_array)"
        numbers starting from the first prime (2).
    
        a loop through all the indexes < size_of_array,
        marking the ones satisfying the relation i^2 + n * i
        as false, i.e. composite numbers, where i - known prime 
        number starting from 2.
    */
    void find_primes(bool sieve[], unsigned int size)
    {
        // by definition 0 and 1 are not prime numbers
        sieve[0] = false;
        sieve[1] = false;
    
        // all numbers <= max are potential candidates for primes
        for (unsigned int i = 2; i <= size; ++i)
        {
            sieve[i] = true;
        }
    
        // loop through the first prime numbers < sqrt(max) (suggested by the algorithm)
        unsigned int first_prime = 2;
        for (unsigned int i = first_prime; i <= std::sqrt(double(size)); ++i)
        {
            // find multiples of primes till < max
            if (sieve[i] = true)
            {
                // mark as composite: i^2 + n * i 
                for (unsigned int j = i * i; j <= size; j += i)
                {
                    sieve[j] = false;
                }
            }
        }
    }
    
    /*
        Function: print_primes()
        Use: print_primes(bool_array, size_of_array);
    
        It prints all the prime numbers, 
        i.e. the indexes with value: true.
    */
    void print_primes(bool sieve[], unsigned int size)
    {
        // all the indexes of the array marked as true are primes
        for (unsigned int i = 0; i <= size; ++i)
        {
            if (sieve[i] == true) 
            {
                std::cout << i <<" ";
            }
        }
    }
    

    covering the array case. A std::vector implementation will include minor changes such as reducing the functions to one parameter, through which the vector is passed by reference and the loops will use the vector size() member function instead of the reduced parameter.

    0 讨论(0)
提交回复
热议问题