Fast exponentiation
Compute base to the power exponent in about log exponent multiplications by squaring the base and using the exponent's binary digits.
O(log n)Space O(1)5 practice problemsStep-through pictureThe idea
Computing 3^13 the slow way takes 12 multiplications: 3 × 3 × 3 × .... For an exponent of a billion, that's a billion multiplications.
Fast exponentiation, also called exponentiation by squaring, uses the binary digits of the exponent. 13 in binary is 1101, which means 13 = 8 + 4 + 1, so 3^13 = 3^8 × 3^4 × 3^1. You can get 3^1, 3^2, 3^4, 3^8 by squaring again and again: each square doubles the power. Then multiply together the ones whose binary digit is 1.
The loop reads the exponent's binary digits from the right: if the lowest digit is 1, multiply the result by the current square. Then square the square and drop the lowest digit. An exponent of a billion has only 30 binary digits, so it takes about 30 steps.
An everyday example
Paying with coins that double in value
Imagine coins worth 1, 2, 4, 8, 16, and so on, each worth double the last. To pay 13, you don't hand over thirteen 1-coins. You pay with an 8, a 4, and a 1. To decide which coins to use, look at 13 in binary: 1101 says use the 8, the 4, and the 1, but not the 2. Fast exponentiation does the same with powers: it builds 3^13 from 3^8, 3^4, and 3^1.
| In the example | In the code |
|---|---|
| The next coin, worth double the last | square *= square |
| Whether to use this coin | e % 2 === 1 |
| Adding the coin to the payment | result *= square |
| Moving on to the next coin size | e = Math.floor(e / 2) |
From the slow way to fast exponentiation
- Start with the obvious way: multiply
baseby itself again and again.3^21takes 20 multiplications, and an exponent of a billion takes a billion. The work grows with the size of the exponent, even though the exponent itself is only a few digits long. - Notice what squaring does.
3^2 × 3^2is3^4, and3^4 × 3^4is3^8: each square doubles the exponent. From3you reach3^16in only 4 squarings. So powers whose exponent is a power of two are cheap. - Every exponent is a sum of powers of two: those are its binary digits.
21is10101in binary, which means16 + 4 + 1. So3^21 = 3^16 × 3^4 × 3^1, and each of those factors is one of the cheap squares. We only need to multiply together the squares whose binary digit is 1. - Read the binary digits from the right while squaring at the same pace.
e % 2is the lowest digit; if it's 1, multiply the currentsquareintoresult. Then squaresquareand drop the digit withe = Math.floor(e / 2). Stop wheneis 0. That loop is fast exponentiation.
How it works
- Set
result = 1,square = base, ande = exponent. - While
e > 0, look at the lowest binary digit ofe:e % 2. - If it is
1, multiplyresultbysquare. - Square
square, so it moves frombase^1tobase^2tobase^4and so on. - Drop the lowest binary digit:
e = Math.floor(e / 2). - When
eis0,resultholdsbase^exponent.
Watch it run
This picture runs the code below on a real input. Press Step to move one step at a time, or Play to watch. The highlighted line is the one that just ran. Change the input to see other cases.
See every step at onceThe same run, laid out side by side
The code
Point at a note to light up the lines it explains.
function power(base, exponent) {let result = 1;let square = base;let e = exponent;while (e > 0) {if (e % 2 === 1) {result *= square;}square *= square;e = Math.floor(e / 2);}return result;}
How fast it is
| Time | O(log n) |
|---|---|
| Extra memory | O(1) |
The exponent n has about log₂ n binary digits, and each loop step handles one. Only three numbers are stored.
- Best case
O(1)exponentis 0 or 1. The loop runs zero times or once. - Average case
O(log n)One loop step per binary digit of the exponent
n. About half the digits are 1, so about 1.5 multiplications per step. - Worst case
O(log n)An exponent whose binary digits are all 1, like
1023(1111111111). Every step multiplies twice: 10 steps and 20 multiplications.
Common mistakes
- Using plain numbers for modular powers with a modulus near
10^9. The product passes2^53and the last digits come out wrong. UseBigIntfor the multiplication. - Forgetting a negative exponent.
base^-nis1 / base^n, so handle the sign first and use the positive exponent in the loop. - Writing
e = e / 2withoutMath.floor.ebecomes a fraction and the loop never sees a clean0. - Using
e & 1ande >> 1with exponents above2^31. Bit operators work on 32-bit integers in JavaScript, so large exponents are cut off. Use% 2andMath.floor(e / 2)orBigInt.
When to use it
Look for these clues in a problem:
- The problem raises something to a huge power, such as
10^9or10^18. - The answer must be given "modulo 1000000007" after a large power.
- Something is applied the same way
ntimes, withnhuge (combine with matrix exponentiation). - You need a modular inverse with a prime modulus (Fermat's rule:
a^(p-2) mod p).
Check yourself
Answer each one in your head first, then open it.
How many loop steps does power(x, 1000) take?
10, because 1000 is 1111101000 in binary, which has 10 digits. Each step handles one digit.
Why can the very last squaring cause trouble even when the answer is small enough?
It squares square once more after the last digit is used. That value is never needed but can be the largest in the loop, so it can overflow or lose precision. Some versions skip the square when e is 1.
What does power(2, -3) return, and why?
1, because e > 0 is false at once and the loop never runs. Negative exponents must be handled before the loop.
Why is it fine that Math.floor(e / 2) throws away the lowest digit?
That digit was just used: if it was 1, square was already multiplied into result. Dropping it moves the next digit into the lowest place for the next step.
Practice problems
Stuck on one? Tuto is in the playground too, and gives you hints, never the answer.
0 of 5 solved. Solve one to earn the bronze medal, half for silver, and all of them for gold.
Start practicingGo further
You don't need these to start practicing. Open one when you want more.
Why it works
The reasoning that makes it always right
The loop keeps one promise at the top of every step: result × square^e equals base^exponent. At the start it reads 1 × base^exponent, so it's true. In the trace, at the row where e = 5, result is 3 and square is 81, and 3 × 81^5 = 3 × 3^20 = 3^21.
Each step keeps the promise. If e is odd, moving one square into result turns square^e into square^(e - 1), and e - 1 is even. Squaring square and halving e leaves square^e unchanged, because (s²)^(e/2) = s^e. Math.floor(e / 2) is the same as (e - 1) / 2 for an odd e, so both cases fit.
The loop ends because e at least halves on every step, so it reaches 0 after as many steps as exponent has binary digits: 5 for 21, 30 for a billion. At that point the promise reads result × square^0 = result, so result equals base^exponent.
Going deeper
3 more ideas
Why it gives the right power
At every step, result × square^e equals the original base^exponent. At the start that's 1 × base^exponent. If e is odd, moving one square into result turns square^e into square^(e-1). Then square^(e-1) with e - 1 even equals (square²)^((e-1)/2), which is exactly what squaring square and halving e does. When e is 0, the rule says result is the answer.
The modular version, and JavaScript numbers
Large powers are usually wanted modulo some m, such as 1000000007. Apply % m after every multiplication: result = (result * square) % m and square = (square * square) % m. But in JavaScript, two numbers near 10^9 multiply to about 10^18, past 2^53, where numbers lose precision. Use BigInt for those products, as in (result * square) % m with 1n-style values, then convert back with Number(...).
The cost
The loop runs once per binary digit of the exponent, so O(log exponent) steps. Each step does at most two multiplications. Computing x^(10^18) takes about 60 steps.
Work it by hand
Every step in a table, with why
Compute 3^21. Its binary digits 10101 alternate, so the trace shows both kinds of step.
base = 3, exponent = 21
| Step | e | e % 2 | result | square after | What happens | Why |
|---|---|---|---|---|---|---|
| 1 | 21 | - | 1 | 3 | start | result starts at 1, which is 3^0. square holds 3^1. |
| 2 | 21 | 1 | 3 | 9 | multiply, then square | The lowest digit of 21 is 1, so 3^1 is part of the answer: result = 3. square becomes 3^2 = 9, and e becomes 10. |
| 3 | 10 | 0 | 3 | 81 | only square | The lowest digit of 10 is 0, so 3^2 is not part of the answer. square becomes 3^4 = 81, and e becomes 5. |
| 4 | 5 | 1 | 243 | 6561 | multiply, then square | Digit 1: result = 3 × 81 = 243, which is 3^5. square becomes 3^8 = 6561, and e becomes 2. |
| 5 | 2 | 0 | 243 | 43046721 | only square | Digit 0: skip 3^8. square becomes 3^16 = 43046721, and e becomes 1. |
| 6 | 1 | 1 | 10460353203 | 1853020188851841 | multiply, then square | Digit 1: result = 243 × 43046721 = 10460353203, which is 3^21. The loop still squares once more, to 3^32, a value it never uses. |
| 7 | 0 | - | 10460353203 | - | e is 0: return | All five binary digits are used up, so result is the answer. |
It returns 10460353203, which is 3^21, after 5 loop steps and 8 multiplications instead of 20. The biggest number in the loop was the unused last square, 3^32.
Compared with other ways
When to pick something else
| Approach | Time | Extra memory | Choose it when |
|---|---|---|---|
| Fast exponentiation | O(log n) | O(1) | Whole exponents, exact or modular answers, and large exponents: the standard choice. |
| Repeated multiplication | O(n) | O(1) | Tiny exponents only, where the simpler loop is easier to read. |
| Recursive squaring | O(log n) | O(log n) | When the recursive form makes a proof or a generic "power of anything" helper clearer. |
Built-in ** or Math.pow | O(1) | O(1) | A floating-point answer is fine and there's no modulus. It can't reduce modulo m along the way. |
Extra memory: O(1): three numbers, result, square, and e. A recursive version uses O(log n) space for its call stack.
How the steps grow
- Fast exponentiation, Recursive squaring
O(log n) - Repeated multiplication
O(n) - Built-in
**orMath.powO(1)
| Approach | n = 10 | n = 1,000 | n = 1,000,000 |
|---|---|---|---|
| Fast exponentiation | 3 | 10 | 20 |
| Repeated multiplication | 10 | 1,000 | 1 million |
| Recursive squaring | 3 | 10 | 20 |
Built-in ** or Math.pow | 1 | 1 | 1 |
Inputs that need care
5 tricky inputs
exponent = 0- The loop never runs and it returns
1, even forpower(0, 0). That matches JavaScript, where0 ** 0is also1. - A negative exponent:
power(2, -3) e > 0is false at once, so it returns1, which is wrong. Handle the sign first:1 / power(base, -exponent)gives0.125.- A negative base:
power(-2, 5) - It works without changes and returns
-32, because the sign is just another factor that gets multiplied in an odd number of times. - A result past
2^53:power(7, 19) - It returns
11398895185373144, but the true value ends in...143. Plain numbers lose the last digits. UseBigIntvalues like7n, or work modulo a number. - A decimal exponent:
power(4, 0.5) e % 2is0.5, never1, andedrops to 0 at once, so it returns1instead of2. The loop only works for whole exponents; use**orMath.sqrtfor fractions.
Variations and follow-ups
Twists interviewers add
Modular power
When the answer is wanted modulo m, reduce after every multiplication: result = result * square % m and square = square * square % m, using BigInt so the products stay exact. This is how modular inverses are computed: b^(m - 2) % m when m is prime.
Recursive squaring
x^n is (x^(n/2))² when n is even and x × x^(n-1) when it's odd. It's the same idea read from the top binary digit down. It's easy to prove, but it uses a call stack of depth log n.
Powers of other things
The loop works for anything with an associative multiply. Raising a matrix to a power jumps a step-by-step rule forward n steps. Composing a shuffle with itself k times gives where each card ends up after k shuffles.
Left-to-right binary
Read the exponent's digits from the highest down: square result at each digit, and multiply by base when the digit is 1. It does the same number of steps, and every multiplication is by the original base, which can be cheaper when base is small.
In an interview
Spot it, explain it, answer follow-ups
- Spot it from a huge exponent ("compute
x^nwherenis up to10^18"), from "modulo10^9 + 7" combined with a power, or from "apply this stepktimes" wherekis huge. - Explain it with the binary digits: "
21is16 + 4 + 1, so I multiply togetherx^16,x^4, andx^1, which I get by squaring." Then say the promise,result × square^estays equal to the answer. - Test
exponent = 0,exponent = 1, a negative exponent, and a power of two like8, where only the last step multiplies intoresult. - The usual follow-up is "what about the modulus and overflow?". Answer: reduce after every multiplication and use
BigInt, because two numbers near10^9multiply to about10^18, past2^53.
Where frontend code uses it
The same idea in real UI code
- The Web Crypto API (
crypto.subtle) supports RSA signatures and encryption, and RSA is built on modular exponentiation of very large numbers. - Exponential backoff for retrying failed requests waits
base × 2^attemptmilliseconds. That power is small, but it is the same idea of repeated doubling. - Teaching tools and code playgrounds that work with
BigIntuse fast exponentiation to compute huge powers, such as2n ** 1000nstyle values, quickly.