From 4d02c70b9291ffca80d3bebc921e22d2c570e2b1 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 26 Sep 2026 04:25:30 +0000 Subject: [PATCH] Keep the sign of a negative base in Pow, and reject undefined powers [patch] Pow computed |x|^p through Math.Log/Math.Exp and never restored the sign, so (-2)^3 returned 8 and (-1)^3 returned 1. A negative base now yields a negative result for odd integer powers. Pow also returned a value where none is defined. It now throws ArgumentException for a negative base with a non-integer power (it returned the real |x|^p), and DivideByZeroException for zero to a negative power (it returned zero). Callers that relied on those wrong values will now see an exception. Fixes ktsu-dev/SignificantNumber#101 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01UHW69XTeuuLbfVdQdJ8uQh --- .../SignificantNumberTests.cs | 42 +++++++++++++++++++ SignificantNumber/SignificantNumber.cs | 19 +++++++-- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/SignificantNumber.Test/SignificantNumberTests.cs b/SignificantNumber.Test/SignificantNumberTests.cs index 640e0b9..42ce997 100644 --- a/SignificantNumber.Test/SignificantNumberTests.cs +++ b/SignificantNumber.Test/SignificantNumberTests.cs @@ -705,6 +705,48 @@ public void Pow_NegativeBaseAndPositiveExponent_ReturnsCorrectResult() Assert.AreEqual(SignificantNumber.CreateFromComponents(0, new BigInteger(9)), result); } + [TestMethod] + public void Pow_NegativeBaseAndOddExponent_ReturnsNegativeResult() + { + SignificantNumber baseNumber = SignificantNumber.CreateFromComponents(0, new BigInteger(-2)); + SignificantNumber power = SignificantNumber.CreateFromComponents(0, new BigInteger(3)); + SignificantNumber result = baseNumber.Pow(power); + + // Expected result is (-2)^3 = -8 + Assert.AreEqual(SignificantNumber.CreateFromComponents(0, new BigInteger(-8)), result); + } + + [TestMethod] + public void Pow_NegativeOneAndOddExponent_ReturnsNegativeOne() + { + SignificantNumber baseNumber = SignificantNumber.CreateFromComponents(0, new BigInteger(-1)); + SignificantNumber power = SignificantNumber.CreateFromComponents(0, new BigInteger(3)); + SignificantNumber result = baseNumber.Pow(power); + + // Expected result is (-1)^3 = -1 + Assert.AreEqual(SignificantNumber.CreateFromComponents(0, new BigInteger(-1)), result); + } + + [TestMethod] + public void Pow_NegativeBaseAndFractionalExponent_ThrowsArgumentException() + { + SignificantNumber baseNumber = SignificantNumber.CreateFromComponents(0, new BigInteger(-2)); + SignificantNumber power = SignificantNumber.CreateFromComponents(-1, new BigInteger(5)); + + // (-2)^0.5 has no real result + Assert.ThrowsExactly(() => baseNumber.Pow(power)); + } + + [TestMethod] + public void Pow_ZeroBaseAndNegativeExponent_ThrowsDivideByZeroException() + { + SignificantNumber baseNumber = SignificantNumber.CreateFromComponents(0, BigInteger.Zero); + SignificantNumber power = SignificantNumber.CreateFromComponents(0, new BigInteger(-1)); + + // 0^-1 is 1/0 + Assert.ThrowsExactly(() => baseNumber.Pow(power)); + } + [TestMethod] public void Operator_Addition_WithPreciseNumber_ReturnsCorrectResult() { diff --git a/SignificantNumber/SignificantNumber.cs b/SignificantNumber/SignificantNumber.cs index cc5d5d0..522f7d0 100644 --- a/SignificantNumber/SignificantNumber.cs +++ b/SignificantNumber/SignificantNumber.cs @@ -561,6 +561,8 @@ internal static bool DoesImplementGenericInterface(Type type, Type genericInterf /// /// The power to raise the significant number to. /// The current number raised to , rounded to the fewest significant digits of the two. + /// Thrown when the current number is zero and is negative. + /// Thrown when the current number is negative and is not an integer, as the result is not a real number. public SignificantNumber Pow(PreciseNumber power) { if (Equal(power, Zero)) @@ -569,18 +571,29 @@ public SignificantNumber Pow(PreciseNumber power) } else if (Equal(this, Zero)) { - return Zero; + return PreciseNumber.IsNegative(power) + ? throw new DivideByZeroException("Cannot raise zero to a negative power.") + : Zero; } else if (Equal(this, One)) { return One; } + bool isNegativeBase = PreciseNumber.IsNegative(Value); + if (isNegativeBase && !PreciseNumber.IsInteger(power)) + { + throw new ArgumentException("Cannot raise a negative number to a non-integer power.", nameof(power)); + } + int significantDigits = LowestSignificantDigits(this, power); - // Use logarithm and exponential to support decimal powers + // Use logarithm and exponential to support decimal powers. This computes |x|^p, so the + // sign of a negative base is restored for odd integer powers. double logValue = Math.Log(Math.Abs(Value.To())); - return Math.Exp(logValue * power.To()).ToSignificantNumber(significantDigits); + double magnitude = Math.Exp(logValue * power.To()); + double result = isNegativeBase && PreciseNumber.IsOddInteger(power) ? -magnitude : magnitude; + return result.ToSignificantNumber(significantDigits); } ///