From d5278c6d6984cc7dfdd1111d49f4fb385c71a15e Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sat, 23 May 2026 23:00:13 +0300 Subject: fix: preserve arbitrary precision in Rat.Compare() for Rat-to-Rat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rat.Compare() converted all types to float64 first, then back to *big.Rat, defeating arbitrary precision. E.g., Rat(1/3) → float64(0.33333...) → imprecise *big.Rat. Now Rat-to-Rat uses direct n.Cmp() for exact comparison. Rat-to-Float still uses float64 → SetFloat64() (acceptable for non-Rat types). --- internal/rpn/number.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/rpn/number.go b/internal/rpn/number.go index f4134b1..562ef77 100644 --- a/internal/rpn/number.go +++ b/internal/rpn/number.go @@ -314,7 +314,14 @@ func (r *Rat) SetMetric(m *Metric) NumericValue { } // Compare returns -1, 0, or 1 if this rational is less than, equal to, or greater than another. +// For Rat-to-Rat comparison, uses direct big.Rat.Cmp() for exact precision. +// For Rat-to-Float comparison, converts via float64 (acceptable precision loss). func (r *Rat) Compare(other NumericValue) (int, error) { + // Rat-to-Rat: direct comparison with full precision + if otherRat, ok := other.(*Rat); ok { + return r.n.Cmp(otherRat.n), nil + } + // Rat-to-Float or other: convert via float64 (acceptable precision loss) otherF, err := other.Float64() if err != nil { return 0, fmt.Errorf("cannot compare: %w", err) -- cgit v1.2.3