The simplest method of screening prime numbers is to remove the multiples of SO 2 from 2, and then remove the multiples of 3 from 3. 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.
[Cpp] // by MoreWindows (http://www.bkjia.com)
Const int MAXN = 100;
Bool flag [MAXN];
Int primes [MAXN/3], pi;
Void GetPrime_1 ()
{
Int I, j;
Pi = 0;
Memset (flag, false, sizeof (flag ));
For (I = 2; I <MAXN; I ++)
If (! Flag [I])
{
Primes [pi ++] = I;
For (j = I; j <MAXN; j + = I)
Flag [j] = true;
}
}
// By MoreWindows (http://www.bkjia.com)
Const int MAXN = 100;
Bool flag [MAXN];
Int primes [MAXN/3], pi;
Void GetPrime_1 ()
{
Int I, j;
Pi = 0;
Memset (flag, false, sizeof (flag ));
For (I = 2; I <MAXN; I ++)
If (! Flag [I])
{
Primes [pi ++] = I;
For (j = I; j <MAXN; j + = I)
Flag [j] = true;
}
}
We can see that there will be a lot of repeated accesses, for example, when accessing flag [2] and flag [5], the access to flag [10] will be performed each time. 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 following steps are similar, and the code is not difficult to write:
[Cpp] // by MoreWindows (http://www.bkjia.com)
Const int MAXN = 100;
Bool flag [MAXN];
Int primes [MAXN/3], pi;
Void GetPrime_2 ()
{
Int I, j;
Pi = 0;
Memset (flag, false, sizeof (flag ));
For (I = 2; I <MAXN; I ++)
{
If (! Flag [I])
Primes [pi ++] = I;
For (j = 0; (j <pi) & (I * primes [j] <MAXN); j ++)
Flag [I * primes [j] = true;
}
}
// By MoreWindows (http://www.bkjia.com)
Const int MAXN = 100;
Bool flag [MAXN];
Int primes [MAXN/3], pi;
Void GetPrime_2 ()
{
Int I, j;
Pi = 0;
Memset (flag, false, sizeof (flag ));
For (I = 2; I <MAXN; I ++)
{
If (! Flag [I])
Primes [pi ++] = I;
For (j = 0; (j <pi) & (I * primes [j] <MAXN); j ++)
Flag [I * primes [j] = true;
}
}
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, our requirement is that each combination be 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. Therefore, 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 after 9*3, 9*5 cannot be used again. Therefore, add another judgment statement in the Code:
[Cpp] // by MoreWindows (http://www.bkjia.com)
Const int MAXN = 100;
Bool flag [MAXN];
Int primes [MAXN/3], pi;
Void GetPrime_2 ()
{
Int I, j;
Pi = 0;
Memset (flag, false, sizeof (flag ));
For (I = 2; I <MAXN; I ++)
{
If (! Flag [I])
Primes [pi ++] = I;
For (j = 0; (j <pi) & (I * primes [j] <MAXN); j ++)
{
Flag [I * primes [j] = true;
If (I % primes [j] = 0) // This sentence ensures that each non-prime number is only screened once.
Break;
}
}
}
// By MoreWindows (http://www.bkjia.com)
Const int MAXN = 100;
Bool flag [MAXN];
Int primes [MAXN/3], pi;
Void GetPrime_2 ()
{
Int I, j;
Pi = 0;
Memset (flag, false, sizeof (flag ));
For (I = 2; I <MAXN; I ++)
{
If (! Flag [I])
Primes [pi ++] = I;
For (j = 0; (j <pi) & (I * primes [j] <MAXN); j ++)
{
Flag [I * primes [j] = true;
If (I % primes [j] = 0) // This sentence ensures that each non-prime number is only screened once.
Break;
}
}
}
Do you want to know the differences between the two sieve prime number methods? Test the prime number between 2 and 0.1 billion to see the difference. The test code is as follows:
[Cpp] // comparison between the ordinary sieve prime number method and the improved efficiency
// By MoreWindows (http://www.bkjia.com)
# Include <stdio. h>
# Include <memory. h>
# Include <time. h>
# Include <math. h>
Const int MAXN = 100000000;
Bool flag [MAXN];
Int primes [MAXN/3], pi;
// Use a multiple of each prime number must not be a prime number to filter.
Void GetPrime_1 ()
{
Int I, j;
Pi = 0;
Memset (flag, false, sizeof (flag ));
For (I = 2; I <MAXN; I ++)
If (! Flag [I])
{
Primes [pi ++] = I;
For (j = I; j <MAXN; j + = I)
Flag [j] = true;
}
}
// A minimum prime factor is required for filtering each sum.
Void GetPrime_2 ()
{
Int I, j;
Pi = 0;
Memset (flag, false, sizeof (flag ));
For (I = 2; I <MAXN; I ++)
{
If (! Flag [I])
Primes [pi ++] = I;
For (j = 0; (j <pi) & (I * primes [j] <MAXN); j ++)
{
Flag [I * primes [j] = true;
If (I % primes [j] = 0)
Break;
}
}
}
Int main ()
{
Printf ("Comparison of ordinary sieve prime number methods with improved efficiency under % d Data Volume \ n", MAXN );
Printf ("by MoreWindows (http://www.bkjia.com) -- \ n ");
Clock_t clockBegin, clockEnd;
ClockBegin = clock ();
GetPrime_1 ();
ClockEnd = clock ();
Printf ("common sieve Prime Number Method \ t % d millisecond \ n", clockEnd-clockBegin );
ClockBegin = clock ();
GetPrime_2 ();
ClockEnd = clock ();
Printf ("Improved sieve Prime Number Method \ t % d millisecond \ n", clockEnd-clockBegin );
Return 0;
}
// Compare the efficiency of the ordinary sieve prime number method with the improved one
// By MoreWindows (http://www.bkjia.com)
# Include <stdio. h>
# Include <memory. h>
# Include <time. h>
# Include <math. h>
Const int MAXN = 100000000;
Bool flag [MAXN];
Int primes [MAXN/3], pi;
// Use a multiple of each prime number must not be a prime number to filter.
Void GetPrime_1 ()
{
Int I, j;
Pi = 0;
Memset (flag, false, sizeof (flag ));
For (I = 2; I <MAXN; I ++)
If (! Flag [I])
{
Primes [pi ++] = I;
For (j = I; j <MAXN; j + = I)
Flag [j] = true;
}
}
// A minimum prime factor is required for filtering each sum.
Void GetPrime_2 ()
{
Int I, j;
Pi = 0;
Memset (flag, false, sizeof (flag ));
For (I = 2; I <MAXN; I ++)
{
If (! Flag [I])
Primes [pi ++] = I;
For (j = 0; (j <pi) & (I * primes [j] <MAXN); j ++)
{
Flag [I * primes [j] = true;
If (I % primes [j] = 0)
Break;
}
}
}
Int main ()
{
Printf ("Comparison of ordinary sieve prime number methods with improved efficiency under % d Data Volume \ n", MAXN );
Printf ("by MoreWindows (http://www.bkjia.com) -- \ n ");
Clock_t clockBegin, clockEnd;
ClockBegin = clock ();
GetPrime_1 ();
ClockEnd = clock ();
Printf ("common sieve Prime Number Method \ t % d millisecond \ n", clockEnd-clockBegin );
ClockBegin = clock ();
GetPrime_2 ();
ClockEnd = clock ();
Printf ("Improved sieve Prime Number Method \ t % d millisecond \ n", clockEnd-clockBegin );
Return 0;
}
Test results:
We can see that the efficiency is 4 times worse. Improvements are impressive. If you are interested, you can refer to the space compression technique mentioned in the next article to compress the space of the improved sieve prime number method.
The following is a summary at the end of the article:
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.
In addition, there are many ways to improve the screening prime number method. You can go to the mathematics forum to study it. This article will not go further.
From MoreWindows