Skip to content

(-1).Pow(2E308) throws OverflowException "The result is too small to represent." instead of returning 1 #117

Description

@matt-edmondson

What happens

Pow special-cases a base of One (SignificantNumber/SignificantNumber.cs:599) but not NegativeOne. When the base is -1 and the integer power is beyond the range of a double, PowByLogarithm computes:

  • Math.Log(1) * power.To<double>(), which is 0 · ∞ = NaN (line 643).
  • It then falls back to Log10OfMagnitude(-1) * ∞, which is NaN again.
  • FromLog10OfMagnitude (around lines 713-718) sees a non-finite value and throws. The message says "too small" only because NaN > 0 is false.
S("-1").Pow(S("2E308"))   // throws OverflowException: The result is too small to represent.  expected 1
S("-1").Pow(S("-1E400"))  // throws the same                                                  expected 1
S("-1").Pow(S("2" + new string('0', 310) + "1")) // throws                                    expected -1
S("-1").Pow(S("1E308"))   // 1 (correct, still inside double range)

Why it matters

The README documents -1, 0 and 1 as exact values. (-1)^n for an integer n always has an exact answer (±1), whatever the size of n. Callers get an exception with a misleading message instead. Impact is limited to very large exponents, but the fix is a two-liner.

Suggested fix

Next to the Equal(this, One) check:

else if (Equal(this, NegativeOne) && PreciseNumber.IsInteger(power))
{
	return PreciseNumber.IsEvenInteger(power) ? One : NegativeOne;
}

IsInteger and IsEvenInteger work on the PreciseNumber directly, without going through a double.

Acceptance criteria

  • (-1)^(2E308) == 1, (-1)^(-1E400) == 1, and (-1)^(odd integer beyond 1E308) == -1.
  • A non-integer power of -1 keeps its current behaviour.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions