From c1f1c8d97394c4269d3838c6bb98f7577e00a3a2 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 3 Nov 2026 17:26:06 +0000 Subject: [PATCH 1/2] Compare a SignificantNumber with a PreciseNumber through Equals [minor] sig.Equals(precise) bound to the record struct's Equals(object), which boxed the PreciseNumber and returned false, while ==, CompareTo and precise.Equals(sig) all reported the values as equal. Add Equals(PreciseNumber) so both argument orders and == agree, and document that a boxed PreciseNumber passed to Equals(object) still compares unequal. Fixes ktsu-dev/SignificantNumber#143 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017vfJW5i3pXEZd4rgcVGix1 --- .../SignificantNumberValueTypeTests.cs | 30 +++++++++++++++++++ SignificantNumber/SignificantNumber.cs | 15 ++++++++++ 2 files changed, 45 insertions(+) diff --git a/SignificantNumber.Test/SignificantNumberValueTypeTests.cs b/SignificantNumber.Test/SignificantNumberValueTypeTests.cs index c4a6b00..d0fd34e 100644 --- a/SignificantNumber.Test/SignificantNumberValueTypeTests.cs +++ b/SignificantNumber.Test/SignificantNumberValueTypeTests.cs @@ -295,4 +295,34 @@ public void CompareAtSignificance_ComparesAtTheLowerSignificantDigitCount(string { Assert.AreEqual(expected, int.Sign(SignificantNumber.CompareAtSignificance(Parse(left), Parse(right)))); } + + [TestMethod] + [DataRow("1.5", "1.5", true)] + [DataRow("1.50", "1.5", true)] + [DataRow("0", "0", true)] + [DataRow("-2.25", "-2.25", true)] + [DataRow("1.5", "1.4", false)] + [DataRow("1.4", "1.5", false)] + public void EqualsPreciseNumber_AgreesInBothArgumentOrdersAndWithOperator(string significant, string precise, bool expected) + { + SignificantNumber s = Parse(significant); + PreciseNumber p = PreciseNumber.Parse(precise, CultureInfo.InvariantCulture); + + Assert.AreEqual(expected, s == p, $"{s} == {p}"); + Assert.AreEqual(expected, s.Equals(p), $"{s}.Equals({p})"); + Assert.AreEqual(expected, p.Equals(s), $"{p}.Equals({s})"); + Assert.AreEqual(expected, s.CompareTo((object)p) == 0, $"{s}.CompareTo((object){p}) == 0"); + } + + [TestMethod] + public void EqualsObject_BoxedPreciseNumber_IsFalseEvenWhenEqual() + { + SignificantNumber s = Parse("1.5"); + object boxed = PreciseNumber.Parse("1.5", CultureInfo.InvariantCulture); + + // The record struct's Equals(object) only accepts another SignificantNumber, so a boxed PreciseNumber is + // never equal to it, although CompareTo(object) treats the two as the same value. + Assert.IsFalse(s.Equals(boxed)); + Assert.AreEqual(0, s.CompareTo(boxed)); + } } diff --git a/SignificantNumber/SignificantNumber.cs b/SignificantNumber/SignificantNumber.cs index 9179e20..ccb5d5c 100644 --- a/SignificantNumber/SignificantNumber.cs +++ b/SignificantNumber/SignificantNumber.cs @@ -846,6 +846,21 @@ private static PreciseNumber ExactIntegerPower(PreciseNumber value, BigInteger e public int CompareTo(SignificantNumber other) => Value.CompareTo(other.Value); + /// + /// Determines whether the current instance holds the same value as a . + /// + /// The precise number to compare with the current instance. + /// if the values are equal; otherwise, . + /// + /// The values are compared exactly, so the result agrees with == and with + /// called the other way round. A boxed as + /// an still goes to through the record's + /// Equals(object), which returns because the object is not a + /// , even though returns zero for it. + /// + public bool Equals(PreciseNumber other) => + Value.Equals(other); + /// /// Compares the current instance with an object. /// From 41a9c2b6d78b3f1abae22d4e360d417e8dc635b4 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 3 Nov 2026 17:35:44 +0000 Subject: [PATCH 2/2] Keep the CompareTo overloads adjacent Move Equals(PreciseNumber) below the last CompareTo overload, which Sonar rule S4136 flagged after it landed between two of them. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017vfJW5i3pXEZd4rgcVGix1 --- SignificantNumber/SignificantNumber.cs | 30 +++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/SignificantNumber/SignificantNumber.cs b/SignificantNumber/SignificantNumber.cs index ccb5d5c..a2005ea 100644 --- a/SignificantNumber/SignificantNumber.cs +++ b/SignificantNumber/SignificantNumber.cs @@ -846,21 +846,6 @@ private static PreciseNumber ExactIntegerPower(PreciseNumber value, BigInteger e public int CompareTo(SignificantNumber other) => Value.CompareTo(other.Value); - /// - /// Determines whether the current instance holds the same value as a . - /// - /// The precise number to compare with the current instance. - /// if the values are equal; otherwise, . - /// - /// The values are compared exactly, so the result agrees with == and with - /// called the other way round. A boxed as - /// an still goes to through the record's - /// Equals(object), which returns because the object is not a - /// , even though returns zero for it. - /// - public bool Equals(PreciseNumber other) => - Value.Equals(other); - /// /// Compares the current instance with an object. /// @@ -906,6 +891,21 @@ obj is SignificantNumber significantNumber ? Value.CompareTo(significantNumber.Value) : Value.CompareTo(obj); + /// + /// Determines whether the current instance holds the same value as a . + /// + /// The precise number to compare with the current instance. + /// if the values are equal; otherwise, . + /// + /// The values are compared exactly, so the result agrees with == and with + /// called the other way round. A boxed as + /// an still goes to through the record's + /// Equals(object), which returns because the object is not a + /// , even though returns zero for it. + /// + public bool Equals(PreciseNumber other) => + Value.Equals(other); + /// /// Returns the absolute value of the specified . ///