Find how many prime numbers are in 0-N

   Problem: Find the number of prime numbers in 0-N.

Preliminary knowledge

  1. 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.
  2. 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).
  3. 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:

  1. Dig out 1 first (because 1 is not a prime number)
  2. 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
  3. Use 3 to remove the numbers after it, and dig out the multiples of 3
  4. Divide these numbers by 4, 5, etc. as divisors. This process continues until all the numbers after the divisor have been dug up.
  5. 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  重复了 ???

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324646527&siteId=291194637