From a9b6bef182ece4a6851112645061e5647cd21367 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 26 Sep 2026 21:23:59 +0000 Subject: [PATCH 1/2] Break MaxMagnitude and MinMagnitude ties by sign, as int and double do [patch] MaxMagnitude and MinMagnitude returned the first argument whenever the two magnitudes were equal, so MaxMagnitude(-2, 2) gave -2 and MinMagnitude(2, -2) gave 2, and the answer depended on argument order. INumberBase, as int, double and decimal implement it, returns the positive value from MaxMagnitude and the negative value from MinMagnitude on a tie. MaxMagnitudeNumber and MinMagnitudeNumber delegate to them and inherit the fix. The existing MinMagnitude tests asserted the old behaviour with (1, -1); they now expect -1. New tests check both argument orders of the tie against int's own MaxMagnitude and MinMagnitude, and the non-tie cases for each sign. Fixes #111 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01QK96a24CjVhUK9u1Ss2YNN --- PreciseNumber.Test/PreciseNumberTests.cs | 32 ++++++++++++++++++++++-- PreciseNumber/PreciseNumber.cs | 24 +++++++++++++++--- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/PreciseNumber.Test/PreciseNumberTests.cs b/PreciseNumber.Test/PreciseNumberTests.cs index 10ea1d1..f586969 100644 --- a/PreciseNumber.Test/PreciseNumberTests.cs +++ b/PreciseNumber.Test/PreciseNumberTests.cs @@ -608,7 +608,7 @@ public void TestStaticMinMagnitude() PreciseNumber one = PreciseNumber.One; PreciseNumber negativeOne = PreciseNumber.NegativeOne; PreciseNumber result = PreciseNumber.MinMagnitude(one, negativeOne); - Assert.AreEqual(one, result); + Assert.AreEqual(negativeOne, result); } [TestMethod] @@ -617,7 +617,35 @@ public void TestStaticMinMagnitudeNumber() PreciseNumber one = PreciseNumber.One; PreciseNumber negativeOne = PreciseNumber.NegativeOne; PreciseNumber result = PreciseNumber.MinMagnitudeNumber(one, negativeOne); - Assert.AreEqual(one, result); + Assert.AreEqual(negativeOne, result); + } + + [TestMethod] + [DataRow(-2, 2)] + [DataRow(2, -2)] + public void TestMagnitudeTiesFollowInt(int x, int y) + { + PreciseNumber px = x.ToPreciseNumber(); + PreciseNumber py = y.ToPreciseNumber(); + + Assert.AreEqual(int.MaxMagnitude(x, y).ToPreciseNumber(), PreciseNumber.MaxMagnitude(px, py)); + Assert.AreEqual(int.MaxMagnitude(x, y).ToPreciseNumber(), PreciseNumber.MaxMagnitudeNumber(px, py)); + Assert.AreEqual(int.MinMagnitude(x, y).ToPreciseNumber(), PreciseNumber.MinMagnitude(px, py)); + Assert.AreEqual(int.MinMagnitude(x, y).ToPreciseNumber(), PreciseNumber.MinMagnitudeNumber(px, py)); + } + + [TestMethod] + [DataRow(-3, 2)] + [DataRow(2, -3)] + [DataRow(3, -2)] + [DataRow(-2, 3)] + public void TestMagnitudeWithoutATiePicksByAbsoluteValue(int x, int y) + { + PreciseNumber px = x.ToPreciseNumber(); + PreciseNumber py = y.ToPreciseNumber(); + + Assert.AreEqual(int.MaxMagnitude(x, y).ToPreciseNumber(), PreciseNumber.MaxMagnitude(px, py)); + Assert.AreEqual(int.MinMagnitude(x, y).ToPreciseNumber(), PreciseNumber.MinMagnitude(px, py)); } [TestMethod] diff --git a/PreciseNumber/PreciseNumber.cs b/PreciseNumber/PreciseNumber.cs index fc17624..49f6b29 100644 --- a/PreciseNumber/PreciseNumber.cs +++ b/PreciseNumber/PreciseNumber.cs @@ -1097,15 +1097,31 @@ public static bool IsZero(PreciseNumber value) => value.Significand == 0; /// - public static PreciseNumber MaxMagnitude(PreciseNumber x, PreciseNumber y) => - x.Abs() >= y.Abs() ? x : y; + /// + /// When the magnitudes are equal, the positive value is returned, as for and . + /// + public static PreciseNumber MaxMagnitude(PreciseNumber x, PreciseNumber y) + { + int comparison = x.Abs().CompareTo(y.Abs()); + return comparison > 0 ? x + : comparison < 0 ? y + : IsNegative(x) ? y : x; + } /// public static PreciseNumber MaxMagnitudeNumber(PreciseNumber x, PreciseNumber y) => MaxMagnitude(x, y); /// - public static PreciseNumber MinMagnitude(PreciseNumber x, PreciseNumber y) => - x.Abs() <= y.Abs() ? x : y; + /// + /// When the magnitudes are equal, the negative value is returned, as for and . + /// + public static PreciseNumber MinMagnitude(PreciseNumber x, PreciseNumber y) + { + int comparison = x.Abs().CompareTo(y.Abs()); + return comparison < 0 ? x + : comparison > 0 ? y + : IsNegative(x) ? x : y; + } /// public static PreciseNumber MinMagnitudeNumber(PreciseNumber x, PreciseNumber y) => MinMagnitude(x, y); From ac58db45a32cf05a68d3f8f387e81dbd0b577b82 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 26 Sep 2026 21:32:51 +0000 Subject: [PATCH 2/2] Replace the nested ternaries in MaxMagnitude and MinMagnitude with an if [patch] SonarCloud S3358 flagged the nested conditional expressions. Behaviour is unchanged. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01QK96a24CjVhUK9u1Ss2YNN --- PreciseNumber/PreciseNumber.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/PreciseNumber/PreciseNumber.cs b/PreciseNumber/PreciseNumber.cs index 49f6b29..8bffab1 100644 --- a/PreciseNumber/PreciseNumber.cs +++ b/PreciseNumber/PreciseNumber.cs @@ -1103,9 +1103,12 @@ public static bool IsZero(PreciseNumber value) => public static PreciseNumber MaxMagnitude(PreciseNumber x, PreciseNumber y) { int comparison = x.Abs().CompareTo(y.Abs()); - return comparison > 0 ? x - : comparison < 0 ? y - : IsNegative(x) ? y : x; + if (comparison != 0) + { + return comparison > 0 ? x : y; + } + + return IsNegative(x) ? y : x; } /// @@ -1118,9 +1121,12 @@ public static PreciseNumber MaxMagnitude(PreciseNumber x, PreciseNumber y) public static PreciseNumber MinMagnitude(PreciseNumber x, PreciseNumber y) { int comparison = x.Abs().CompareTo(y.Abs()); - return comparison < 0 ? x - : comparison > 0 ? y - : IsNegative(x) ? x : y; + if (comparison != 0) + { + return comparison < 0 ? x : y; + } + + return IsNegative(x) ? x : y; } ///