Faster integer power algorithm

Source: Internet
Author: User

I believe that integer power operations, as an example of algorithm evolution, are even more appropriate. In order to save the valuable learning time for visitors, we can skip the introduction of recursion and other basic concepts that may be involved. If any errors are found in the text, please open your clothes and correct them.

Because suitable test data is necessary for testing performance, this article uses the C ++ large number class for demonstration.

Click to get C ++ big data class source code

Here we will first list the algorithm analysis technology that will be mentioned:

Dynamic Planning

REDUCTION AND CONTROL LAW

Test Platform:

  • Linux
  • G ++ 4.7

Original Recursive MethodThis does not take much time to repeat.

BigInteger pow(BigInteger x, int N) {  if (N == 1) {     return x;  }  if (N == 0) {      return 1;  }  return pow(x, N - 1) * x;}

190000

The result value fluctuates up and down. The fluctuation scope depends on the process scheduling of the operating system. Obviously, the time complexity is O (n ). Obviously, this algorithm has room for improvement. For recursion, a recursive algorithm consumes a certain amount of recursive call stack space according to its algorithm during execution (note, this does not take into account the compiler's tail recursion optimization), and function calls will carry out parameter pressure stacks, store necessary information and other operations, resulting in a certain call overhead, therefore, it comes with space complexity. O (n) can be changed to iterative version computing to save these costs. However, tests have found that the time has not significantly improved, so we can try to optimize it to a better version of Iterative Computing to save costs. So the next improvement we made was to apply recursion. How do you think I cannot figure it out? Do not care about these details.

Better recursive Calculation Method

At the beginning of the article, the definition of the governing law of reduction has been given. Similar to the governing law of division, we will not go into details. (? ?) Wikipedia description:

A divide and conquer algorithm works by recursively breaking down a problem into two or more sub-Problems of the same (or related) type, until these become simple enough to be solvdirectly

To solve this problem, we can start with this formula:

 

Sorry, you have not figured out how to use the plug-in to generate the latex formula on live writer.

For x ^ 64, we can break it into x ^ 32? X ^ 32. In this way, to get the value of x ^ 64, we only need to calculate the value of x32 and then multiply it. Similarly, in order to get the value of x ^ 32, we need to get the value of x ^ 16, and so on, so that we can get a process:

X ^ 2 = x? X

X ^ 4 = x ^ 2? X ^ 2

X ^ 8 = x ^ 4? X ^ 4

X ^ 16 = x ^ 8? X ^ 8

X ^ 32 = x ^ 16? X ^ 16

X ^ 64 = x ^ 32? X ^ 32

As a result, we can see that the original 64-time multiplication is required. Here we only need 6 times. When the power is an odd number, we will not waste any ink. The derivation process is more complex than that when the power is an even number, everyone can deduce the formula by themselves.

We can know that the scale of an algorithm actually depends on the power. Therefore, we can simplify the overall analysis of an algorithm to the power analysis. If the power is set to N, there will be 2I = n, where I is the multiplication number

I = logn

Of course, this is only theoretical. The specific analysis is slightly complicated.

Finally, we provide the implementation code:

BigInteger pow(BigInteger x, int N) {  if (N == 1) {      return x;  }  if (N == 0) {      return 1;  }  if (N % 2 == 0) {      return pow(x * x, N >>= 2);  } else {      return x*pow(x*x, N>>=/2);  }}
Test x = 13, n = 6000 and get the running time 30000. We can see that the time is much reduced, and the space complexity O (logn) is relatively negligible, you can test it on your own machine. All in all, our algorithms have been improved. However, this is not enough. After all, function calls still have overhead. Can we optimize it into Iterative Computing? How much time will it save?

Power of iterative versions

Before implementing iterative versions, we need to consider several issues. 1. Since it is an iteration, it can only be from X? X starts, but what is the difference between this and the original recursive version? 2. Do I need to use multiple threads? But we are optimizing the algorithm itself. 3. How can I create a power? It seems that the improved recursive version has already been done. Is there anything to do with X itself?

Now that iteration is required and fast, we have to save intermediate results like an improved recursive algorithm (refer to dynamic planning). But what if we save intermediate results? How do we know the intermediate results for a number? It doesn't matter if you think about it. You can ask the masters and elders for help. This is also a kind of feeling ~~~ After guidance from the master, it turns out that, like the improved recursive version, the expression of x ^ n does not need to be changed.

X2 = x? X

X4 = x2? X2

X8 = X4? X4

X16 = X8? X8

X32 = x16? X16

X64 = x32? X32

In addition, N can be expressed as the addition of a certain number of 2. If n is an odd number, it is still the original problem after the value is reduced by 1. So far, can we convert the binary representation of N to the corresponding decimal operation? Now that you know the direction, you can use the following solution.

BigInteger quick_pow(BigInteger x, int N) {//boundary condition if (x == 0) {     return 0; } if (x == 1 || N == 0) {     return 1; }//store x,x^2,x^4...until x^2^logN int n = log2(N); BigInteger arr[n + 1]; arr[0] = x; for (int i = 1; i <= n; i++) {     arr[i] = arr[i - 1] * arr[i - 1]; } BigInteger result = 1; int count = 0; while (N != 1) //Calculating result according to the binary representation of N. {     switch (N % 2) {     case 1:     result *= arr[count];     break;     case 0:     break; }     count += 1;     N >>= 2; }     result *= arr[count];     return result;}
Now the improvement is complete, saving some hidden overhead, and the running time is not much different from the recursive version of the release version after testing. The code is not well written and needs to be rewritten. It can be shared if it is better.

Finally, I recommend a book titled "Algorithm Analysis and Design Basics", which introduces some main analysis technologies of algorithms from the perspective of algorithm IDEA classification. It is worth looking.

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.