diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-23 23:00:13 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-23 23:00:13 +0300 |
| commit | d5278c6d6984cc7dfdd1111d49f4fb385c71a15e (patch) | |
| tree | d5b540cdc599c1d149a781d32f84f35d9879d800 | |
| parent | 79852fdaa2464c9e364f2f564f9b981814270926 (diff) | |
fix: preserve arbitrary precision in Rat.Compare() for Rat-to-Rat
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).
| -rw-r--r-- | internal/rpn/number.go | 7 |
1 files changed, 7 insertions, 0 deletions
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) |
