diff --git a/PreciseNumber.Test/PreciseNumberTests.cs b/PreciseNumber.Test/PreciseNumberTests.cs index ae3c204..29f8236 100644 --- a/PreciseNumber.Test/PreciseNumberTests.cs +++ b/PreciseNumber.Test/PreciseNumberTests.cs @@ -1056,6 +1056,26 @@ public void TestReduceSignificance() Assert.AreEqual(number, number.ReduceSignificance(5)); } + // A precision below one has no meaning, and used to return a wrong number rather than fail: + // 5 reduced to zero digits came back as 10, and to minus one digit as 0. + + [TestMethod] + [DataRow(0)] + [DataRow(-1)] + [DataRow(int.MinValue)] + public void TestReduceSignificanceRejectsAPrecisionBelowOne(int significantDigits) + { + Assert.ThrowsExactly(() => 5.ToPreciseNumber().ReduceSignificance(significantDigits)); + Assert.ThrowsExactly(() => PreciseNumber.Pi.ReduceSignificance(significantDigits)); + } + + [TestMethod] + public void TestReduceSignificanceThrowsWhenTheExponentLeavesTheIntRange() + { + PreciseNumber number = PreciseNumber.CreateFromComponents(int.MaxValue - 1, 12345); + Assert.ThrowsExactly(() => number.ReduceSignificance(3)); + } + [TestMethod] public void TestReduceSignificanceRoundsHalfAwayFromZeroOnTheDroppedDigits() { diff --git a/PreciseNumber/PreciseNumber.cs b/PreciseNumber/PreciseNumber.cs index 68184fb..520f46c 100644 --- a/PreciseNumber/PreciseNumber.cs +++ b/PreciseNumber/PreciseNumber.cs @@ -857,8 +857,15 @@ internal long CountDecimalDigits() => /// The number of significant digits to reduce to. /// A new instance of reduced to the specified number of significant digits. /// Rounds half away from zero, so 123.5 becomes 124 and 123.456 becomes 123 at three digits. + /// Thrown when is less than one. + /// Thrown when the result needs an exponent outside the range of an . public PreciseNumber ReduceSignificance(int significantDigits) { + if (significantDigits < 1) + { + throw new ArgumentOutOfRangeException(nameof(significantDigits), significantDigits, "At least one significant digit is required."); + } + int significantDifference = significantDigits < SignificantDigits ? SignificantDigits - significantDigits : 0; @@ -868,9 +875,7 @@ public PreciseNumber ReduceSignificance(int significantDigits) return this; } - int newExponent = Exponent == 0 - ? significantDifference - : Exponent + significantDifference; + int newExponent = checked(Exponent + significantDifference); BigInteger newSignificand = DropDigitsRoundingHalfAwayFromZero(Significand, significantDifference); return new(newExponent, newSignificand); }