Skip to content

fix(pow-x-n): correctness bug — JavaScript iterative solution returns wrong answer for n = INT_MIN - #6044

Open
neetcode-gh wants to merge 1 commit into
mainfrom
fix/pow-x-n-js-int-min
Open

fix(pow-x-n): correctness bug — JavaScript iterative solution returns wrong answer for n = INT_MIN#6044
neetcode-gh wants to merge 1 commit into
mainfrom
fix/pow-x-n-js-int-min

Conversation

@neetcode-gh

Copy link
Copy Markdown
Owner

The bug

In articles/pow-x-n.md, the JavaScript snippet for approach 3 (Binary Exponentiation, Iterative) produces a wrong answer for n = -2147483648.

Input Expected Published JS
x = 2.00000, n = -2147483648 0.00000 1.00000

That is LeetCode's own published test case for this problem.

Why

Math.abs(-2147483648) is fine on its own — JavaScript numbers are doubles, so it correctly yields 2147483648. The problem is the bit loop: & and >> apply ToInt32 to their operands first.

let power = Math.abs(n);   // 2147483648

power & 1     // ToInt32(2147483648) === -2147483648  ->  -2147483648 & 1  ->  0
power >>= 1   // -2147483648 >> 1  ->  -1073741824

So the odd-bit multiply is skipped, power goes negative, the power > 0 guard fails, and the loop exits after one iteration with res still 1. The function returns 1 / 1 = 1.

Why only JavaScript

Every other language in the same tab group already widens the exponent to 64 bits before the loop, so none of them were affected:

Language Widening
Java Math.abs((long)n)
C++ abs((long)n)
C# Math.Abs((long)n)
Kotlin Math.abs(n.toLong())
Rust (n as i64).abs()
Go int is 64-bit
Swift Int is 64-bit
Python arbitrary precision

JavaScript was the only one that computed abs correctly and then threw the width away again inside the loop.

The article's own "Integer Overflow When Negating n" pitfall section warns about exactly this trap, which made the JS snippet the one place in the article that didn't follow its own advice.

The recursive JavaScript solution (approach 2) was already correct — it uses Math.floor(n / 2) and n % 2, not bitwise ops.

The fix

Replace the two bitwise operations with their arithmetic equivalents, which keep power a full-precision double. Structure, naming, and style are otherwise unchanged, and it now matches how the recursive JS solution already worked.

 while (power > 0) {
-    if (power & 1) {
+    if (power % 2 === 1) {
         res *= x;
     }
     x *= x;
-    power >>= 1;
+    power = Math.floor(power / 2);
 }

Also added one sentence to the pitfall section covering the JavaScript-specific form of the trap, so the next reader doesn't "optimize" it back to bitwise.

Verification

Run against the production NeetCode judge with the article-solution harness, using a test set that includes x = 2.00000, n = -2147483648 (expected 0.00000):

  • Before: Binary Exponentiation (Iterative) / javascript — Wrong Answer, 33/34, Expected: 0.00000 / Actual: 1.00000
  • After: javascript passes 34/34

All 9 languages then pass both binary exponentiation approaches (18/18 submissions), confirming JavaScript was the only affected language:

Binary Exponentiation (Iterative): python PASS, java PASS, cpp PASS, javascript PASS,
                                   csharp PASS, go PASS, kotlin PASS, swift PASS, rust PASS
Binary Exponentiation (Recursive): python PASS, java PASS, cpp PASS, javascript PASS,
                                   csharp PASS, go PASS, kotlin PASS, swift PASS, rust PASS

(Approach 1, Brute Force, is O(n) and times out on the |n| ~ 2^31 stress cases by design.)

Note for the problem config

The existing n = -2147483648 case in the problem's test set uses x = -1.00000 with expected output 1.00000. That case does not discriminate this bug: (-1)^(-2^31) = 1, and the broken code also returns 1 (it exits the loop immediately with res = 1). A case with |x| != 1, such as x = 2.00000, n = -2147483648 -> 0.00000, is what actually catches it, and may be worth adding.

🤖 Generated with Claude Code

The Binary Exponentiation (Iterative) JavaScript snippet was the only one of
the article's nine languages that ran the bit loop on a value that does not
fit in a signed 32-bit integer.

`Math.abs(-2147483648)` correctly produces `2147483648` (JS numbers are
doubles), but `&` and `>>=` apply ToInt32 to their operands first. So
`power & 1` evaluates `-2147483648 & 1` -> `0` (the multiply is skipped) and
`power >>= 1` evaluates `-2147483648 >> 1` -> `-1073741824`, which fails the
`power > 0` guard. The loop exits after a single iteration with `res` still 1.

On LeetCode's own published test case `x = 2.00000, n = -2147483648`
(expected `0.00000`) the snippet returned `1`.

Every other language already widens to 64 bits before the loop --
`Math.abs((long)n)` in Java/C#, `abs((long)n)` in C++, `(n as i64).abs()` in
Rust, `n.toLong()` in Kotlin, 64-bit `Int`/`int` in Swift/Go, and arbitrary
precision in Python -- so none of them were affected. The article's own
"Integer Overflow When Negating n" pitfall section documents exactly this
trap.

Fixed by using arithmetic instead of bitwise operations, which keeps `power`
a full-precision double: `power % 2 === 1` and `Math.floor(power / 2)`. The
recursive JavaScript solution already did this and was correct. Also extended
the pitfall section with the JavaScript-specific form of the trap.

Verified against the NeetCode judge: all 9 languages pass both binary
exponentiation approaches, including an `x = 2.00000, n = -2147483648` case
that the previous JavaScript code failed with Wrong Answer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Aug 2, 2026

Copy link
Copy Markdown

Skipping Bugbot: Bugbot is disabled for this repository. Visit the Bugbot dashboard to update your settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant