Summary of filtering prime numbers:
The simplest method to screen prime numbers isStart from 2, remove the multiples of SO 2, and then start from 3, remove the multiples of 3, and proceed in sequence.. According to this, it is easy to write the code. The code below is to screen the prime number method to obtain the prime number less than 100 and save it to the PRIMES [] array.
1 const int maxn = 100; 2 bool flag [maxn]; 3 int primes [maxn/3], PI; 4 void getprime_1 () 5 {6 int I, J; 7 PI = 0; 8 memset (flag, false, sizeof (FLAG); 9 for (I = 2; I <maxn; I ++) 10 if (! Flag [I]) 11 {12 primes [Pi ++] = I; 13 for (j = I; j <maxn; j + = I) // remove the multiples of the data to be tested J and set its flag bit to true14 flag [J] = true; 15} 16}
We can see that this willThere are many repeated accessesFor example, when you access flag [2] and flag [5], each flag [10] is accessed. Therefore, it is best to reduce this type of repeated access so that each element of the Flag [] array is accessed only once. You can consider this --The simple screening prime number method is to use a prime number multiple must not be a prime number, similarly, the product of any number and all other prime numbers is certainly not a prime number (this is because each union number must have a minimum prime factor ).
To test this idea, we first use a number between 2 and 10.
Flag is unlabeled at the beginning of 2, 3, 4, 5, 6, 7, 8, 9, and 10.
Step 1 Access 2, flag [2] is not marked, SO 2 is added to the prime number table, and then the number obtained by multiplying all the numbers in the prime number table 2 is not a prime number, 2*2 = 4 so flag [4].
2, 3, 4, 5, 6, 7, 8, 9, 10
Step 2 Access 3, flag [3] is not marked, so 3 is added to the prime number table. The number obtained by multiplying 3 with all the numbers in the prime number table must not be a prime number, 3*2 = 6, 3*3 = 9 so flag [6] and flag [9] are marked.
2, 3, 4, 5, 6, 7, 8, 9, 10
Step 3 Access 4, flag [4] is marked so 4 is not added to the prime number table, the number obtained by multiplying 4 with all the numbers in the prime number table must not be a prime number, 4*2 = 8, 4*3 = 12 so flag [8].
2, 3, 4, 5, 6, 7, 8, 9, 10
Step 4 access 5, flag [5] is not marked, so 5 is added to the prime number table. The number obtained by multiplying all the numbers in the five and prime number tables must not be a prime number, 5*2 = 10, 5*3 = 15 so flag [10].
2, 3, 4, 5, 6, 7, 8, 9, 10
Step 5 Access 6. Flag [6] is marked so 6 is not added to the prime number table. The number obtained by multiplying all the numbers in the 6 and prime number tables must not be a prime number, 6*2 = 12, 6*3 = 18, 6*5 = 30.
2, 3, 4, 5, 6, 7, 8, 9, 10
The next steps are similar,CodeAs follows:
1 const int maxn = 100; 2 bool flag [maxn]; 3 int primes [maxn/3], PI; 4 void getprime_2 () 5 {6 int I, J; 7 PI = 0; 8 memset (flag, false, sizeof (FLAG); 9 for (I = 2; I <maxn; I ++) 10 {11 if (! Flag [I]) 12 primes [Pi ++] = I; // flag is not marked as true and is added to the prime number table 13 for (j = 0; (j <PI) & (I * primes [J] <maxn); j ++) // removes the product of the data to be investigated and the data in the prime number table in sequence, set its flag position to true14 flag [I * primes [J] = true; 15} 16}
Is this code correct? Looking back at the analysis process, we can find that some data is still accessed multiple times. This is certainly not the expected result.The requirement is that each combination is screened only once by its smallest prime factor.. For example, the minimum prime factor of 12 is 2, so it should only be accessed when 6*2 is calculated, and should not be accessed when 4*3 is calculated, similarly, 18 should only be accessed when computing 9*2, and should not be accessed when computing 6*3.
Find out the cause and then think about how to solve it. 6*3 does not work, but 9*2 does. Because 6 is a multiple of 2, after 6*2 is calculated, 6 cannot be multiplied by a prime number greater than 2, the result of multiplication will inevitably lead to repeated calculation. So for any number,If it is a multiple of the prime number, it cannot be multiplied by the prime number after the prime number in the prime number table.For example, 9 is a multiple of 3, so 9*5 cannot be used after 9*3. Therefore, add another judgment statement in the Code:
1 const int maxn = 100; 2 bool flag [maxn]; 3 int primes [maxn/3], PI; 4 void getprime_2 () 5 {6 int I, J; 7 PI = 0; 8 memset (flag, false, sizeof (FLAG); 9 for (I = 2; I <maxn; I ++) 10 {11 if (! Flag [I]) 12 primes [Pi ++] = I; 13 (J = 0; (j <PI) & (I * primes [J] <maxn); j ++) 14 {15 flag [I * primes [J] = true; 16 if (I % primes [J] = 0) // This statement ensures that each non-prime number is screened only once for 17 break; 18} 19} 20}
Do you want to know the differences between the two sieve prime number methods? Now we can test the prime number between 2 and 0.1 billion to see how big the difference is,Test codeAs follows:
1/* 2 * Description: screen prime number method (Multiple elimination, minimum prime factor filtering) Comparison 3 * Analysis: Multiple elimination: the multiple of a prime number must not be a prime number, that is, from 2, remove the multiples of 2, and then remove the multiples of 3 from 3, and then perform filtering by the 4 * least prime factor: simple screening prime number method (multiple removal) the multiples of a prime number must not be a prime number. Similarly, the product of any number and all other prime numbers must not be a prime number (this is because each union must have a minimum prime factor ). 5 The requirement is that each sum be screened only by its smallest prime factor. That is, if it is a multiple of the prime number, it cannot be multiplied by the prime number after the prime number in the prime number table. 6*7*8 */9 # include <stdio. h> 10 # include <stdlib. h> 11 # include <memory. h> 12 # include <time. h> 13 # include <math. h> 14 const int maxn = 100000000; 15 bool flag [maxn]; 16 int primes [maxn/3], PI; 17 // use a multiple of each prime number must not be a prime number to filter 18 void getprime_1 () 19 {20 int I, j; 21 Pi = 0; 22 memset (flag, false, sizeof (FLAG); 23 for (I = 2; I <maxn; I ++) 24 if (! Flag [I]) 25 {26 primes [Pi ++] = I; 27 for (j = I; j <maxn; j + = I) 28 flag [J] = true; 29} 30} 31 // a minimum prime factor is required for each combination to filter 32 void getprime_2 () 33 {34 int I, J; 35 Pi = 0; 36 memset (flag, false, sizeof (FLAG); 37 for (I = 2; I <maxn; I ++) 38 {39 if (! Flag [I]) 40 primes [Pi ++] = I; 41 for (j = 0; (j <PI) & (I * primes [J] <maxn ); j ++) 42 {43 flag [I * primes [J] = true; 44 if (I % primes [J] = 0) 45 break; 46} 47} 48} 49 int main () 50 {51 printf ("Comparison of ordinary sieve prime number methods with improved efficiency under % d Data Volume \ n ", maxn); 52 clock_t clockbegin, clockend; 53 54 clockbegin = clock (); 55 getprime_1 (); 56 clockend = clock (); 57 printf ("common sieve Prime Number Method \ t % d millisecond \ n", clockend-clockbegin); 58 59 clockbegin = clock (); 60 getprime_2 (); 61 clockend = clock (); 62 printf ("Improved sieve Prime Number Method \ t % d millisecond \ n", clockend-clockbegin); 63 system ("pause "); 64 return 0; 65}
The specific running result is as follows:
Summary:
1. The principle of a common screening prime number is that the multiple of a prime number must not be a prime number.
2. The principle of improved sieve prime number is that each combination number must have a minimum prime factor. Removing the number of elements based on each minimum prime factor can prevent duplicate accesses to the combination number.
I am the dividing line of tiantiao
Reference: http://www.cnblogs.com/xymqx/p/3718276.html