From cd58e39baae6cf82dfc11b616ca505d6f0836a8d Mon Sep 17 00:00:00 2001 From: Sam Brossard Date: Thu, 12 Nov 2026 09:40:03 -0800 Subject: [PATCH] fix(maths): detect long overflow in Pow.pow Pow.pow multiplied into a long without overflow checks, so results above Long.MAX_VALUE silently wrapped (e.g. pow(2, 63) returned Long.MIN_VALUE). Use Math.multiplyExact so overflow throws ArithmeticException, and update the Javadoc (negative bases are valid; document the new exception). Fixes #1 Co-Authored-By: Claude Opus 5.5 --- src/main/java/com/thealgorithms/maths/Pow.java | 7 +++++-- src/test/java/com/thealgorithms/maths/PowTest.java | 12 ++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/thealgorithms/maths/Pow.java b/src/main/java/com/thealgorithms/maths/Pow.java index 377b37ac4569..19d40d868e17 100644 --- a/src/main/java/com/thealgorithms/maths/Pow.java +++ b/src/main/java/com/thealgorithms/maths/Pow.java @@ -16,12 +16,15 @@ private Pow() { *

* The method calculates {@code a}{@code b} by iteratively multiplying the base {@code a} with itself {@code b} times. * If the exponent {@code b} is negative, an {@code IllegalArgumentException} is thrown. + * If the exact result does not fit in a {@code long}, an {@code ArithmeticException} is thrown + * instead of silently returning a wrapped-around value. *

* - * @param a the base of the exponentiation. Must be a non-negative integer. + * @param a the base of the exponentiation. * @param b the exponent to which the base {@code a} is raised. Must be a non-negative integer. * @return the result of {@code a}{@code b} as a {@code long}. * @throws IllegalArgumentException if {@code b} is negative. + * @throws ArithmeticException if the result overflows a {@code long}. */ public static long pow(int a, int b) { if (b < 0) { @@ -29,7 +32,7 @@ public static long pow(int a, int b) { } long result = 1; for (int i = 1; i <= b; i++) { - result *= a; + result = Math.multiplyExact(result, a); } return result; } diff --git a/src/test/java/com/thealgorithms/maths/PowTest.java b/src/test/java/com/thealgorithms/maths/PowTest.java index 4309b0f10ed5..e5d5d1f2da43 100644 --- a/src/test/java/com/thealgorithms/maths/PowTest.java +++ b/src/test/java/com/thealgorithms/maths/PowTest.java @@ -33,4 +33,16 @@ void testPowHandlesZeroBase() { void testPowHandlesOneBase() { assertEquals(1, Pow.pow(1, 100)); } + + @ParameterizedTest + @CsvSource({"2, 62, 4611686018427387904", "-2, 63, -9223372036854775808", "-3, 3, -27", "-2, 4, 16", "10, 18, 1000000000000000000"}) + void testPowAtAndNearLongBounds(int base, int exponent, long expected) { + assertEquals(expected, Pow.pow(base, exponent)); + } + + @ParameterizedTest + @CsvSource({"2, 63", "2, 64", "-2, 64", "10, 19", "2147483647, 3"}) + void testPowThrowsOnOverflow(int base, int exponent) { + assertThrows(ArithmeticException.class, () -> Pow.pow(base, exponent)); + } }