From bea052dbf6f6df0e2e26b45108a5e3f7d5a23e61 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 22:23:32 +0000 Subject: [PATCH] =?UTF-8?q?Return=20=C2=B11=20from=20(-1).Pow=20for=20an?= =?UTF-8?q?=20integer=20power=20beyond=20double=20range=20[patch]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pow special-cased a base of One but not NegativeOne, so (-1)^n for an integer n outside the range of a double fell through to PowByLogarithm, computed 0 * infinity = NaN and threw OverflowException("The result is too small to represent."). (-1)^n is exact for any integer n, so return One for an even power and NegativeOne for an odd one, decided on the PreciseNumber without going through a double. A non-integer power of -1 still throws ArgumentException. Fixes ktsu-dev/SignificantNumber#117 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MiwudJMQgsVwkkrRfMfwG2 --- .../SignificantNumberRangeTests.cs | 20 +++++++++++++++++++ SignificantNumber/SignificantNumber.cs | 5 +++++ 2 files changed, 25 insertions(+) diff --git a/SignificantNumber.Test/SignificantNumberRangeTests.cs b/SignificantNumber.Test/SignificantNumberRangeTests.cs index f2864f9..423607b 100644 --- a/SignificantNumber.Test/SignificantNumberRangeTests.cs +++ b/SignificantNumber.Test/SignificantNumberRangeTests.cs @@ -56,6 +56,26 @@ public void Exp_ResultBelowDoubleRange_ReturnsNonzeroMagnitude() Assert.AreEqual(Parse("5.07595889755E-435"), result); } + [TestMethod] + [DataRow("2E308", "1")] + [DataRow("-1E400", "1")] + [DataRow("1E308", "1")] + [DataRow("-3E400", "1")] + public void Pow_NegativeOneToAnEvenIntegerBeyondDoubleRange_ReturnsOne(string power, string expected) => + Assert.AreEqual(Parse(expected), SignificantNumber.NegativeOne.Pow(Precise(power))); + + [TestMethod] + public void Pow_NegativeOneToAnOddIntegerBeyondDoubleRange_ReturnsNegativeOne() + { + PreciseNumber oddPower = Precise("2" + new string('0', 310) + "1"); + Assert.AreEqual(SignificantNumber.NegativeOne, SignificantNumber.NegativeOne.Pow(oddPower)); + Assert.AreEqual(SignificantNumber.NegativeOne, SignificantNumber.NegativeOne.Pow(PreciseNumber.Negate(oddPower))); + } + + [TestMethod] + public void Pow_NegativeOneToANonIntegerPower_StillThrowsArgumentException() => + Assert.ThrowsExactly(() => SignificantNumber.NegativeOne.Pow(Precise("0.5"))); + [TestMethod] public void Pow_PowerOfTenBeyondExponentRange_ThrowsOverflowException() { diff --git a/SignificantNumber/SignificantNumber.cs b/SignificantNumber/SignificantNumber.cs index f879e51..9179e20 100644 --- a/SignificantNumber/SignificantNumber.cs +++ b/SignificantNumber/SignificantNumber.cs @@ -605,6 +605,11 @@ public SignificantNumber Pow(PreciseNumber power) { return One; } + else if (Equal(this, NegativeOne) && PreciseNumber.IsInteger(power)) + { + // (-1)^n is exact for any integer n, however far beyond the range of a double it is. + return PreciseNumber.IsEvenInteger(power) ? One : NegativeOne; + } bool isNegativeBase = PreciseNumber.IsNegative(Value); if (isNegativeBase && !PreciseNumber.IsInteger(power))