aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Roose <stevenroose@gmail.com>2018-03-20 01:08:23 +0800
committerVictor Quinn <mail@victorquinn.com>2018-03-20 01:08:23 +0800
commit2df3e6ddaf6e9531dd02d7b6337f2d310f5e4f22 (patch)
treeb3a358a7ea14356e29d2b18a655eb5bb2bbedc16
parent69b3a8ad1f5f2c8bd855cb6506d18593064a346b (diff)
downloaddexon-decimal-2df3e6ddaf6e9531dd02d7b6337f2d310f5e4f22.tar.gz
dexon-decimal-2df3e6ddaf6e9531dd02d7b6337f2d310f5e4f22.tar.zst
dexon-decimal-2df3e6ddaf6e9531dd02d7b6337f2d310f5e4f22.zip
Add support for shifting in base 10 (#86)
This allows for very fast multiplying and dividing by powers of 10 without the possibility of losing precision.
-rw-r--r--decimal.go12
-rw-r--r--decimal_test.go29
2 files changed, 41 insertions, 0 deletions
diff --git a/decimal.go b/decimal.go
index 20aa608..ad92a90 100644
--- a/decimal.go
+++ b/decimal.go
@@ -376,6 +376,18 @@ func (d Decimal) Mul(d2 Decimal) Decimal {
}
}
+// Shift shifts the decimal in base 10.
+// It shifts left when shift is positive and right if shift is negative.
+// In simpler terms, the given value for shift is added to the exponent
+// of the decimal.
+func (d Decimal) Shift(shift int32) Decimal {
+ d.ensureInitialized()
+ return Decimal{
+ value: new(big.Int).Set(d.value),
+ exp: d.exp + shift,
+ }
+}
+
// Div returns d / d2. If it doesn't divide exactly, the result will have
// DivisionPrecision digits after the decimal point.
func (d Decimal) Div(d2 Decimal) Decimal {
diff --git a/decimal_test.go b/decimal_test.go
index 25ad751..ac80089 100644
--- a/decimal_test.go
+++ b/decimal_test.go
@@ -925,6 +925,7 @@ func TestDecimal_Uninitialized(t *testing.T) {
a.Add(b),
a.Sub(b),
a.Mul(b),
+ a.Shift(0),
a.Div(New(1, -1)),
a.Round(2),
a.Floor(),
@@ -1096,6 +1097,34 @@ func TestDecimal_Mul(t *testing.T) {
}
}
+func TestDecimal_Shift(t *testing.T) {
+ type Inp struct {
+ a string
+ b int32
+ }
+
+ inputs := map[Inp]string{
+ Inp{"6", 3}: "6000",
+ Inp{"10", -2}: "0.1",
+ Inp{"2.2", 1}: "22",
+ Inp{"-2.2", -1}: "-0.22",
+ Inp{"12.88", 5}: "1288000",
+ Inp{"-10234274355545544493", -3}: "-10234274355545544.493",
+ Inp{"-4612301402398.4753343454", 5}: "-461230140239847533.43454",
+ }
+
+ for inp, expectedStr := range inputs {
+ num, _ := NewFromString(inp.a)
+
+ got := num.Shift(inp.b)
+ expected, _ := NewFromString(expectedStr)
+ if !got.Equal(expected) {
+ t.Errorf("expected %v when shifting %v by %v, got %v",
+ expected, num, inp.b, got)
+ }
+ }
+}
+
func TestDecimal_Div(t *testing.T) {
type Inp struct {
a string