Segmented Sieve of Eratosthenes?

后端 未结 5 532
伪装坚强ぢ
伪装坚强ぢ 2020-11-22 13:15

It\'s easy enough to make a simple sieve:

for (int i=2; i<=N; i++){
    if (sieve[i]==0){
        cout << i << \" is prime\" << endl;
           


        
5条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-11-22 13:56

    Based on Swapnil Kumar answer I did the following algorithm in C. It was built with mingw32-make.exe.

    #include
    #include
    #include
    
    int main()
    {
        const int MAX_PRIME_NUMBERS = 5000000;//The number of prime numbers we are looking for
        long long *prime_numbers = malloc(sizeof(long long) * MAX_PRIME_NUMBERS);
        prime_numbers[0] = 2;
        prime_numbers[1] = 3;
        prime_numbers[2] = 5;
        prime_numbers[3] = 7;
        prime_numbers[4] = 11;
        prime_numbers[5] = 13;
        prime_numbers[6] = 17;
        prime_numbers[7] = 19;
        prime_numbers[8] = 23;
        prime_numbers[9] = 29;
        const int BUFFER_POSSIBLE_PRIMES = 29 * 29;//Because the greatest prime number we have is 29 in the 10th position so I started with a block of 841 numbers
        int qt_calculated_primes = 10;//10 because we initialized the array with the ten first primes
        int possible_primes[BUFFER_POSSIBLE_PRIMES];//Will store the booleans to check valid primes
        long long iteration = 0;//Used as multiplier to the range of the buffer possible_primes
        int i;//Simple counter for loops
        while(qt_calculated_primes < MAX_PRIME_NUMBERS)
        {
            for (i = 0; i < BUFFER_POSSIBLE_PRIMES; i++)
                possible_primes[i] = 1;//set the number as prime
    
            int biggest_possible_prime = sqrt((iteration + 1) * BUFFER_POSSIBLE_PRIMES);
    
            int k = 0;
    
            long long prime = prime_numbers[k];//First prime to be used in the check
    
            while (prime <= biggest_possible_prime)//We don't need to check primes bigger than the square root
            {
                for (i = 0; i < BUFFER_POSSIBLE_PRIMES; i++)
                    if ((iteration * BUFFER_POSSIBLE_PRIMES + i) % prime == 0)
                        possible_primes[i] = 0;
    
                if (++k == qt_calculated_primes)
                    break;
    
                prime = prime_numbers[k];
            }
            for (i = 0; i < BUFFER_POSSIBLE_PRIMES; i++)
                if (possible_primes[i])
                {
                    if ((qt_calculated_primes < MAX_PRIME_NUMBERS) && ((iteration * BUFFER_POSSIBLE_PRIMES + i) != 1))
                    {
                        prime_numbers[qt_calculated_primes] = iteration * BUFFER_POSSIBLE_PRIMES + i;
                        printf("%d\n", prime_numbers[qt_calculated_primes]);
                        qt_calculated_primes++;
                    } else if (!(qt_calculated_primes < MAX_PRIME_NUMBERS))
                        break;
                }
    
            iteration++;
        }
    
        return 0;
    }
    

    It set a maximum of prime numbers to be found, then an array is initialized with known prime numbers like 2, 3, 5...29. So we make a buffer that will store the segments of possible primes, this buffer can't be greater than the power of the greatest initial prime that in this case is 29.

    I'm sure there are a plenty of optimizations that can be done to improve the performance like parallelize the segments analysis process and skip numbers that are multiple of 2, 3 and 5 but it serves as an example of low memory consumption.

提交回复
热议问题