diff --git a/decimal.go b/decimal.go index a6e7d56..3892a26 100644 --- a/decimal.go +++ b/decimal.go @@ -158,6 +158,18 @@ func NewFromFloatWithExponent(value float64, exp int32) Decimal { } } +// NewFromRat returns a decimal from a big.Rat representation. +func NewFromRat(value *big.Rat) Decimal { + // fast path, where Rat is an int + if value.IsInt() { + f, _ := value.Float64() + return New(int64(math.Floor(f)), 0) + } + + floatValue, _ := value.Float64() + return NewFromFloat(floatValue) +} + // rescale returns a rescaled version of the decimal. Returned // decimal may be less precise if the given exponent is bigger // than the initial exponent of the Decimal. diff --git a/decimal_test.go b/decimal_test.go index e4f82fb..855a4ff 100644 --- a/decimal_test.go +++ b/decimal_test.go @@ -2,6 +2,7 @@ package decimal import ( "math" + "math/big" "testing" ) @@ -59,6 +60,26 @@ func TestNewFromFloat(t *testing.T) { } } +func TestNewFromRat(t *testing.T) { + // add negatives + for f, s := range testTable { + if f > 0 { + testTable[-f] = "-" + s + } + } + + for f, s := range testTable { + r := big.NewRat(0, 1) + r.SetFloat64(f) + d := NewFromRat(r) + if d.String() != s { + t.Errorf("expected %s, got %s (%s, %d)", + s, d.String(), + d.value.String(), d.exp) + } + } +} + func TestNewFromString(t *testing.T) { // add negatives for f, s := range testTable {