When we need to calculate the value of some number `base`

raised to the power of another number `exp`

we can do so naively using the following algorithm:

```
def power(base, exp):
result := 1
for i = 1 to exp:
result *= base
return result
```

The problem with this algorithm is that it is very slow, its complexity is `O(exp)`

which is linear in the value of the exponent.

To solve this problem, there is a simple algorithm called Power By Squaring or just "Fast Power" algorithm.

It is built on the observation that we can manipulate the exponentiation into a sequence of squaring, here are some examples:

- \( a^4 = (a^2)^2 \) -- Can be calculated in 2 steps (instead of 4)
- \( a^8 = ((a^2)^2)^2 \) -- Can be calculated in 3 steps (instead of 8)
- \( a^3 = a * a^2 \) -- Can be calculated in 2 steps (instead of 3)
- \( a^5 = a * (a^2)^2 \) -- Can be calculated in 3 steps (instead of 5)
- \( a^{12} = ((a * a^2)^2)^2 \) -- Can be calculated in 5 steps (instead of 12)

For this we can write a simple recursive algorithm:

```
def fast_power(base, exp):
// Base conditions
if exp == 1: return base
if exp == 0: return 1
// The recursive definitions
if exp % 2 == 0: return fast_power(base * base, exp / 2)
return base * fast_power(base, exp-1)
```

The sense of this algorithm is the following:

- If you can split the current power in 2, then you can factor out the 2, calculate square the base, and now you have half the power remaining. i.e. \( a^{2e} = (a^2)^e \)
- If you can't split the current power in 2, then subtract 1 of that power, multiply that 1 manually, and recurse (which will lead you to the first case). i.e. \(a^{2e+1} = a * a^{2e} \)

And of course we need the 2 base conditions to specify when we are going to end our loop.

Now, thanks to halfing the exponent on each step, the **complexity** of this algorithm is `O(log(exp))`

. Which is much better than what we had before.

### One last bit

In problem solving we are often required to calculate a huge exponent and get the result module some constant. knowing that the modulus operator can be distributed on multiplication, i.e. `(a * b) % m = ( (a % m) * (b % m)) % m`

, we can update the fast power algorithm to accomodate for that:

```
def fast_power(base, exp, mod):
// Base conditions
if exp == 1: return base
if exp == 0: return 1
// The recursive definitions
if exp % 2 == 0: return fast_power((base * base) % mod, exp / 2, mod)
return (base * fast_power(base, exp-1, mod)) % mod
```

### Conclusion

In conclusion, the Fast Power algorithm is a fast and efficient way to calculate exponents with a complexity of O(log(exp)). It can also be modified to calculate the result modulo a constant if needed. You can now use this algorithm to improve the performance of your code when dealing with large exponents.

If you think this article was useful, leave me a reaction and/or a comment. If you think people in your circle can make use of this article feel free to share it.