Binary Exponentiation
Learn via video course
Abstract
Binary Exponentiation is a technique of computing a number raised to some quantity, which can be as small as or as large as in a fast and efficient manner. It utilises the property of exponentiation and the fact that any number can be represented as sum of powers of two depending on its binary notation to get an edge over the naive brute force method.
Scope of article
- This article explains what is binary exponetiation, where it can be used and it's implementation.
- This article shows the implementation of binary exponentiation in C++ only.
Takeaways
- Complexity of Binary exponentiation
- Time complexity -
Introduction of Binary Exponentiation
Exponentiation means raising a number to a power. If we raise to the power , it means we multiply with itself times.
If we look carefully at the definition, it means that to find a raised to the power of b or , we would need to perform the muliplication operation b times.
There can be two ways to compute exponentiation : iterative method by using a for loop or by using recursion. Let us see both of these methods in detail.
Iterative Way
In this method, we use a for loop to multiply a with itself b times. As we use a for loop to iterate b times, it is called the iterative method.
Output
As we can see in the above code, the for loop runs a total of times, and each time we multiply answer with , so that in the end answer variable contains multiplied times or .
The for loop runs times, so the complexity of above code is , where is the exponent or the power the number is being raised to.
Recursive Way
In this method, we use recursion to compute . Recursion is a function calling itself with smaller parameters until a base condition is reached. For exponentiation, the base condition will be when . In such a case we just return 1, in all other cases, we multiply the answer by , and recurse for .
Output
In this case, we recurse until becomes 0, that means we call the recursive function a total of times, making the complexity in this case also.
So, this makes the time complexity of exponentiation as , where is the exponent or the power the number is being raised to.
Now, if is of the order of or , then it means the code described above will run for a total of or times, which is a lot!
So, when dealing with large values of , this algorithm is much expensive and time consuming. This is where Binary Exponentiation comes into the picture.
Why Binary Exponentiation?
If we can somehow find a way to make our exponentiation faster, we would be able to compute for large values of also. This is exactly what Binary Exponentiation does.
By using Binary Exponentiation, we can compute in only operations. That means we now only need to perform multiplications to find out the value of . We will explore more about the time complexity of binary exponentiation in detail after we define it in the next sections.
Let us explore the intuition behind Binary Exponentiation and also its algorithm in the next section.
Algorithm
How does Binary Exponentiation achieve logarithmic time complexity?
Let us explore the intuition behind the algorithm before we define it.
Intuition
Binary Exponeniation uses the property of exponentiation and the fact that any number can be represented as sum of powers of two depending on its binary notation, to compute the final answer. According to the property of exponentiation,
This means, that if we want to compute and we have already computed values of and , we require only one multiplication operation to get the final answer to .
Now if we look at b in its binary representation, we will be able to write b as a sum of powers of two.
As an example let us take a = 5 and b = 12. 12 in binary is represented as :
In powers of two, we can re-write it as
In other words 12 can be represented as a sum of and .
So, if we want to compute with a = 5 and b = 12, we can rewrite it as :
In other words, the problem boils down to representing as the sum of powers of two and then computing raised to only those powers of two and multiplying them together. Like, here as 12 can be expressed as a sum of and , we only need to compute and and multiply them together to get to the final answer.
But here again, computing requires 4 operations, and computing requires eight operations. Combining this with one operation to multiply them together, we get a total of (4+8+1) = 13 operations, which is not an improvement over the previous method.
The thing to notice here is that now we have to only compute and then multiply them together. We can use this to our benefit in the sense that if we have raised to a power of two, say computed, where x is a power of two, to compute , where and is also a power of two, we don't need to start from scratch, we can instead keep multiply with itself to get the next power of two, and keep doing this until we reach .
This follows directly from one other property of exponents, which is :
So, if we have computed where b is a power of two, then to get the value raised to the next power of 2, we just need to compute , which requires only one multiplication operation, which is . This way we can get the required and multipying them together will give us the final answer.
Consider the previous example of and , we already saw we need to multiply and . Now, instead of computing by multipying four times, we instead start computing 5 raised to powers of 2 starting from 0. So, we compute , then by multiplying the previous values together and so on.
Hence, we can compute the values of and in 4 operations and only one more operation (multiplying and ) is needed to get the final answer.
Time Complexity
So, we get to the final answer in just 5 operations, as opposed to 12 operations if we did the exponentiation the brute force way.
The final complexity of this algorithm turns out to be , because atmost all bits in the binary representation of will be set, so we will have to compute raised to atmost power of 2, and multiplying them together will take more operations.
Hence, the overall complexity is , where b is the exponent.
Actual Algorithm
So, we start by computing raised to , i.e, , then multiply these together to get ,then multiply these together to get and so on. But, we multiply in the answer only those values of whose bits in are set, as they will be the only ones that sum upto , as discussed above.
To know if the nth bit in is set, we can use with 1 bit shifted by n, i.e, and check if the result is non-zero. Conversely, we can keep dividing by 2 during iterations and just find out its remainder every time to check if the bit is set or not. This is equivalent to converting into its binary representation.
Note in the algorithm, that we only multiply in the answer when the bit is set, as only those values of sum upto .
The algorithm to compute is :
This algorithm can be implemented by recursion as well as in the iterative method. Both of these have been described in detail in the next section.
Implementation of Binary Exponentiation
There are two approaches to the above defined algorithm, both of which we will discuss in detail in this section.
Recursive Approach
A recursive approach is one in which the recursive function calls itself with slightly smaller parameter, until the base case is reached.
For binary exponentiation, our base case will be when our exponent, i.e b in , turns 0. In such a case, we simply return 1 irrespective of a.
For all other cases, we follow the algorithm defined above. If the current bit in b is set, that is if b leaves a remainder of one when divided by two, then we recurse for (b-1)/2 and multiply it twice with a and return it. Else, b gives a remainder zero when divided by 2 and hence the current bit is unset, so we just recurse for b/2 and multiply it twice and return it.
Iterative Approach
In the iterative approach we follow the same logic, but without recursion. Instead, we use a while loop to perform the same operations, until b is greater than 0.
The time complexity of both these solutions is the same and equal to , though the recursive solution has an overhead of recursive calls.
Applications of Binary Exponentiation
- In cryptography, large exponents with modulo of a number are widely used. To compute large exponents, binary exponentiation is a fast method which finds an application in this field.
- We can efficiently compute large exponents modulo some large number by this technique. This particular application is useful in solving many mathematical problems.
- This can be used to compute modular multiplicative inverse of a number.
- Basically, this method is very useful for problems where we need to compute exponentiation in a speedy fashion.
Conclusion
- Binary Exponentiation is a technique of computing a number raised to some quantity in a fast and efficient manner.
- It uses properties of exponentiation and binary numbers for fast computation.
- It has time complexity of O(log(b)) where b is the power any number is being raised to.
- It finds its applications in cryptography and in other mathematical problems where computation of exponents is required.