Evaluate the number of prime numbers in n (n> = 3) using algorithms

Source: Internet
Author: User


First, let's talk about the definition of prime numbers. What is a prime number? Except 1 and itself, it cannot be divisible by other natural numbers (except 0 ).

It is called a prime number (prime number); otherwise it is called a union number.


According to the definition of prime numbers, to solve this problem, I first thought of traversing each odd number from 3 to N, and then dividing by three

The odd number between the root number N can be used to calculate the number of prime numbers.


The following code is compiled:

(The code is written in C ++)

# Include <iostream> # include <time. h> using namespace STD; # define n 000000int compuprimen (INT); int main (char argc, char * argv []) {int itimes = clock (); int inum = compuprimen (n); int itimee = clock (); cout <inum <Endl; cout <"algorithm time: "<itimee-itimes <" millisecond "<Endl; getchar (); Return 0;} int compuprimen (INT maxnum) {// algorithm 1int inum = 1; // start with 2 bool bprime = true; For (INT I = 3; I <= maxnum; I + = 2) {bprime = true; For (Int J = 3; j <= (INT) SQRT (I); j + = 2) {if (I % J = 0) {bprime = false; break ;}} if (bprime) inum ++;} return inum ;}
After running:


It can be seen that the algorithm performance is not very good, and there is still much room for optimization in time.

So how should we optimize it?

First, I want to see if I can remove the multiples of 2, but later

It is found that the first remainder in the second loop is 3, so the multiples of 3 are actually calculated only once.

It filters out, and there is no need to think further.

Later I thought, in the second loop, 3 times out of the remainder. If the loop is not exceeded, 6, 9, and so on

You do not need to continue to get the remainder. Similarly, if you get the remainder of 5, you should not continue to get the remainder of 10, 15... because the remainder is obtained.

5 is not 0, so the remainder 10, 15 is certainly not 0. In other words, the remainder should not be actually a sum !!

Why? Because if it is a combination of numbers, it is bound to be able to obtain the remainder of a number smaller than its own number, that is

Previously, we wanted to filter out the numbers that do not want to get the remainder. In this way, we only need to get the remainder in the second loop.

It can be determined by a smaller prime number than its root number! However, before we calculate the prime number

Find out, so we just need to record it !!


As a result, I have rewritten the compuprimen () function and written 2nd algorithms:

Int compuprimen (INT maxnum) {// algorithm 2int inum = 1; // record the total number of prime numbers int irecn = 1; // record the number of prime numbers in the array bool bprimen = true; int sqrtmaxn = (INT) SQRT (maxnum); // we want to record the prime numbers smaller than sqrtmaxn. In order to make the space allocation optimal, the size is X/ln (x) * 1.2, // because scientists have found an approximate formula X/ln (x) for calculating the approximate range of prime numbers. // to avoid array out-of-bounds, add a 20% range. // note that maxnum is a special case when it is 3, because Ln (root 3) is 0int * iprime = new int [maxnum = 3? 1: (INT) (float) sqrtmaxn/log (sqrtmaxn) * 1.2)]; for (INT I = 3; I <= maxnum; I + = 2) {bprimen = true; // you only need to obtain the prime number in the remainder range. For (Int J = 1; j <irecn; j ++) {if (I % iprime [J] = 0) {bprimen = false; break;} If (bprimen) {if (I <= sqrtmaxn) {iprime [irecn] = I; irecn ++; inum = irecn;} elseinum ++ ;}} Delete iprime; return inum ;}
After running:


Look, after optimization, the algorithm's time performance is about 19 times better than the original one,

Can it be faster?

I think it works theoretically, because the previous algorithms use an idea,

Filter out multiples of 2 and 3 in advance. If we can add multiples of 5, 7, and 11

Isn't it faster to filter it out beforehand?

Why is there no 9 here, because the multiples of 9 are the multiples of 3, then? It seems

What we found is a bit similar to the idea of algorithm 2. If we can filter out

If the prime number is a multiple, isn't it possible to filter out many aggregate numbers? For this prime number + 1,

There are two situations: one is the sum of filtered out, and the other is the prime number,

Otherwise, it should be filtered out before !! In the process of filtering,

Isn't it the prime number that we want to count the unfiltered data that we encounter?

In this way, can time performance be further optimized? Yes, but in advance

Filtering out so many combinations and recording their behaviors consumes a lot

Space. This is a typical space change time !!


So the algorithm 3 I wrote was born, as follows:

Int compuprimen (INT maxnum) {// algorithm 3 // use a bool-type large array to record. True indicates a prime number, and false indicates an even number. // calculate the number of prime numbers, so the first two can be ignored. bool * barray = new bool [maxnum + 1]; for (INT I = 2; I <= maxnum; I ++) barray [I] = true; int inum = 0; for (INT I = 2; I <= maxnum; I ++) {// Replace the sum behind the sieve with falseif (barray [I]) {inum ++; for (Int J = I + I; j <= maxnum; j + = I) {barray [J] = false ;}} Delete barray; return inum ;}
After running


Wow! I did not expect that the algorithm time could be optimized so quickly !! However, it seems like the space consumed

There are a lot of storage. It seems a waste to use only bool-type array records. Can I use 0 or 1 on each bit?

To replace records?

So I wrote the following algorithm:

Int compuprimen (INT maxnum) {// algorithm 4 // each digit 0 or 1 is used to represent the sum and prime number respectively. // The advantage is that the maximum int size of memory space = maxnum % 8 = 0? Maxnum/8: maxnum/8 + 1; unsigned char * array = new unsigned char [size]; for (INT I = 0; I <size; I ++) array [I] = 127; int inum = 0, ibit = 0, Index = 0; For (INT I = 2; I <= maxnum; I ++) {Index = I/8; (ibit = I % 8) = 0? Ibit = 7, index --: ibit --; If (array [Index] & (1 <ibit) {inum ++; For (Int J = I + I; j <= maxnum; j + = I) {Index = J/8; (ibit = J % 8) = 0? Ibit = 7, index --: ibit --; array [Index] = array [Index] & (~ (1 <ibit) ;}} Delete array; return inum ;}
Running result


Although binary computing makes the time performance slower than algorithm 3,

However, if BIT is used to record the prime number or sum, the storage space is changed to the original 1/8,

The advantage is self-evident. If there is no memory space problem, so is algorithm 3.

Naturally, if you have strict requirements on memory space, algorithm 2 is the best

Preferred.


Summary:

In thinking and coding, I deeply realized the importance of algorithm optimization.

A good programmer must understand that algorithms are the soul of a program !!

Evaluate the number of prime numbers in n (n> = 3) using algorithms

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.