Problem: Find the number of prime numbers in 0-N.
Preliminary knowledge
- What is a prime number: A prime number (also called a prime number) is the opposite of a composite number. The only factors of a prime number are 1 and itself , for example: 7 = 1 * 7. And 6 = 1 * 6 = 2 * 3, so 6 is not prime. Rule: 0 and 1 are neither prime nor composite.
- Determining prime numbers: If a number x is prime, then in the integer range [2,√x] , no integer can be found that divides x. Why just try √x instead of n-1? (It is definitely not n, because n is himself, and judging n is the same as judging 1, which is meaningless).
- The origin of √x : A positive number n can be expressed as: n = √n * √n . There are two possibilities for the two factors of n: • Both factors are √n • One factor is greater than √n, and the other must be less than √n. If we can't find a factor in the range 2 to √n, then we can't find another factor in the range √n to n-1. And what prime numbers are expecting is that they can't find two factors in the range from 2 to n-1, but only expect the factors to be 1 and n?
stage one
1 public void countPrime_1( int n) {
2
3 // The reason why the array range is set to n+1 is because the array starts counting from the subscript 1, and n represents the last number
4 // The initial value of the array is false, because we Assuming false means prime, true means not prime
5 boolean [] b = new boolean [n + 1 ];
6
7 // 2 - n Each number is judged one by one
8 for ( int i = 2; i <= n; i++ ) {
9 // [2, √i]
10 for ( int j = 2; j * j <= i; j++ ) {
11 if (i % j == 0 ) {
12 // In the process of judging whether i is a prime number, traverse 2 - √i
13 // Once it is found that in [2, √i], there are integer divisions, set the subscript i in the array b to true,
14 / / Represents not a prime number, and interrupts the inner for loop, because it has been judged that i is not a prime number, there is no need to
15 // Continue the loop to judge. Directly judge the i+1th number
16 b[i] = true ;
17 break ;
18 }
19 }
20 }
21
22 /**
23 * This part of the content will not be written in the next
24 */
25 int count = 0 ;
26 // The subscript starts from 2, because 1 is neither a prime nor a composite number, there is no need to judge
27 for( int i = 2; i <= n; i++ ) {
28 // When false, it represents the prime number
29 if (b[i] == false ) {
30 count++ ;
31 }
32 }
33 }
Note: Inside the for loop in line 10, you are using j * j <= i , not j <= sqrt(i). Reason: First: sqrt is used to deal with floating point numbers, and the calculation speed of floating point numbers is much slower than that of integer. Second, function calls are also time-wasting. Third: storage errors of floating-point numbers may lead to fatal errors, such as sqrt(9) may be equal to 2.9999999, then int(sqrt(9)) is equal to 2 instead of 3.
stage two
Screening method: Write all the integers 1-n on a piece of paper, and then judge whether they are prime numbers one by one, find a non-prime number, dig it out, and the last remaining is the prime number.
The specific methods are as follows:
- Dig out 1 first (because 1 is not a prime number)
- Use 2 to remove the numbers after it, and dig out the numbers that are divisible by 2, that is, dig out the multiples of 2
- Use 3 to remove the numbers after it, and dig out the multiples of 3
- Divide these numbers by 4, 5, etc. as divisors. This process continues until all the numbers after the divisor have been dug up.
- The remaining numbers are prime numbers
1 public void countPrime_2( int n) {
2
3 boolean [] b = new boolean [n + 1 ];
4
5 for ( int p = 2; p * p <= n; p++ ) {
6 // Assume when p is When it is 2, that is, it is judged whether the value with the subscript 2 in the array b is false, that is, whether the number 2 is a prime number
7 // If it is a prime number, the multiples of 2, 4 6 8 10, etc. are all marked as non-prime numbers, That is, b[2] b[4] b[6] is true
8 if (b[p] == false ) {
9 /**
10 * When p is 3, j = 3 * 3 = 9 . Hey? ? ? How to directly mark 9 as a non-prime number? ? ?
11 * Shouldn't 6 be marked as non-prime first? Mark 9 directly, what about 6? ? ?
12 * Because: 6 is also a multiple of the prime number 2, when calculating the prime number 2, 6 has been removed by
13 * So start the calculation directly from p * p, which is equivalent to optimizing
14 * j = j + p means jumping to p next multiple of
15 */
16 for ( int j = p * p; j <= n; j = j + p) {
17 if (b[j] == false ) {
18 b[j] = true ;
19 }
20 }
21 }
22 }
23 }
对于一个数p,会依次去除 p*p , p*(p+1) , p*(p+2) .... p*(p+k) 【p*(p+k)<=n】
前面不是说要去除 p 的所有倍数的吗?那 p*2 ,p*3, p*4 ... p*(p-1)怎么不去除呢?
他们已经被去除了。因为当前我们要消去 p 的倍数,那么,之前一定去除了 2 3 4 ... p-3 , p-2 ,p-1 的这些数 的倍数,举个例子:之前一定去除了 2*p 3*p 4*p (p-1)*p。所以 , 当想去除p的倍数时,如果我们还是去除 p*2 p*3 p*4 p*(p-1) 那么岂不是与 我们去除2的倍数时 会去除 2*p 、去除3的倍数时 会去除 3*p、去除4的倍数时 会去除 4*p 重复了 ???