Skip to content

Commit 7959f3e

Browse files
committed
Implement rationalize
Signed-off-by: James Hamlin <jfhamlin@gmail.com>
1 parent 1a32274 commit 7959f3e

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

pkg/lang/bigdecimal.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,17 @@ import (
77
"bitbucket.org/pcastools/hash"
88
)
99

10-
// BigDec is an arbitrary-precision decimal number. It wraps and has
11-
// the same semantics as big.Float. big.Float is not used directly
12-
// because it is mutable, and the core BigDecimal should not be.
10+
// BigDec is an arbitrary-precision floating point number. It wraps
11+
// and has the same semantics as big.Float. big.Float is not used
12+
// directly because it is mutable, and the core BigDecimal should not
13+
// be.
14+
//
15+
// TODO: swap out with a *decimal* representation. The go standard
16+
// library big.Float is a binary floating point representation,
17+
// which means that some decimal fractions cannot be represented
18+
// exactly. This can lead to unexpected results when doing
19+
// arithmetic with decimal fractions. A decimal representation
20+
// would avoid this problem.
1321
type BigDecimal struct {
1422
val *big.Float
1523
}

pkg/lang/numbers.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,26 @@ func (nm *NumberMethods) Remainder(x, y any) any {
9898
return Ops(x).Combine(yops).Remainder(x, y)
9999
}
100100

101+
func (nm *NumberMethods) Rationalize(x any) any {
102+
switch x := x.(type) {
103+
case float32:
104+
return nm.Rationalize(NewBigDecimalFromFloat64(float64(x)))
105+
case float64:
106+
return nm.Rationalize(NewBigDecimalFromFloat64(x))
107+
case *BigDecimal:
108+
bx := x.val
109+
rat, _ := bx.Rat(nil)
110+
if rat.IsInt() {
111+
return NewBigIntFromGoBigInt(rat.Num())
112+
}
113+
return &Ratio{val: rat}
114+
}
115+
if !IsNumber(x) {
116+
panic(fmt.Errorf("cannot rationalize %T", x))
117+
}
118+
return x
119+
}
120+
101121
func (nm *NumberMethods) And(x, y any) any {
102122
return bitOpsCast(x) & bitOpsCast(y)
103123
}

0 commit comments

Comments
 (0)