mirror of
https://github.com/shopspring/decimal.git
synced 2024-11-23 12:50:49 +01:00
Merge 1b31f22216
into a1bdfc355e
This commit is contained in:
commit
c2735d73b8
2 changed files with 233 additions and 1 deletions
99
decimal.go
99
decimal.go
|
@ -1513,7 +1513,7 @@ func (d Decimal) StringFixedCash(interval uint8) string {
|
||||||
return rounded.string(false)
|
return rounded.string(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round rounds the decimal to places decimal places.
|
// Round rounds the decimal to places decimal places (half away from zero).
|
||||||
// If places < 0, it will round the integer part to the nearest 10^(-places).
|
// If places < 0, it will round the integer part to the nearest 10^(-places).
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
|
@ -1544,6 +1544,103 @@ func (d Decimal) Round(places int32) Decimal {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RoundHalfTowardZero rounds the decimal to places decimal places (half toward zero).
|
||||||
|
// If places < 0, it will round the integer part to the nearest 10^(-places).
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// NewFromFloat(5.45).RoundHalfTowardZero(1).String() // output: "5.4"
|
||||||
|
// NewFromFloat(545).RoundHalfTowardZero(-1).String() // output: "540"
|
||||||
|
func (d Decimal) RoundHalfTowardZero(places int32) Decimal {
|
||||||
|
if d.exp == -places {
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
// truncate to places + 1
|
||||||
|
ret := d.rescale(-places - 1)
|
||||||
|
|
||||||
|
// add sign(d) * 0.4
|
||||||
|
if ret.value.Sign() < 0 {
|
||||||
|
ret.value.Sub(ret.value, fourInt)
|
||||||
|
} else {
|
||||||
|
ret.value.Add(ret.value, fourInt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// floor for positive numbers, ceil for negative numbers
|
||||||
|
_, m := ret.value.DivMod(ret.value, tenInt, new(big.Int))
|
||||||
|
ret.exp++
|
||||||
|
if ret.value.Sign() < 0 && m.Cmp(zeroInt) != 0 {
|
||||||
|
ret.value.Add(ret.value, oneInt)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// RoundHalfUp rounds the decimal half towards +infinity.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// NewFromFloat(545).RoundHalfUp(-2).String() // output: "500"
|
||||||
|
// NewFromFloat(500).RoundHalfUp(-2).String() // output: "500"
|
||||||
|
// NewFromFloat(1.1001).RoundHalfUp(2).String() // output: "1.10"
|
||||||
|
// NewFromFloat(-1.454).RoundHalfUp(1).String() // output: "-1.4"
|
||||||
|
// NewFromFloat(-1.464).RoundHalfUp(1).String() // output: "-1.5"
|
||||||
|
func (d Decimal) RoundHalfUp(places int32) Decimal {
|
||||||
|
if d.exp == -places {
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
// truncate to places + 1
|
||||||
|
ret := d.rescale(-places - 1)
|
||||||
|
|
||||||
|
// add sign(d) * 0.5 if sign(d) >= 0 else sign(d) * 0.4
|
||||||
|
if ret.value.Sign() < 0 {
|
||||||
|
ret.value.Sub(ret.value, fourInt)
|
||||||
|
} else {
|
||||||
|
ret.value.Add(ret.value, fiveInt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// floor for positive numbers, ceil for negative numbers
|
||||||
|
_, m := ret.value.DivMod(ret.value, tenInt, new(big.Int))
|
||||||
|
ret.exp++
|
||||||
|
if ret.value.Sign() < 0 && m.Cmp(zeroInt) != 0 {
|
||||||
|
ret.value.Add(ret.value, oneInt)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// RoundHalfDown rounds the decimal half towards -infinity.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// NewFromFloat(550).RoundHalfDown(-2).String() // output: "500"
|
||||||
|
// NewFromFloat(560).RoundHalfDown(-2).String() // output: "600"
|
||||||
|
// NewFromFloat(1.1001).RoundHalfDown(2).String() // output: "1.10"
|
||||||
|
// NewFromFloat(-1.454).RoundHalfDown(1).String() // output: "-1.5"
|
||||||
|
// NewFromFloat(-1.444).RoundHalfDown(1).String() // output: "-1.4"
|
||||||
|
func (d Decimal) RoundHalfDown(places int32) Decimal {
|
||||||
|
if d.exp == -places {
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
// truncate to places + 1
|
||||||
|
ret := d.rescale(-places - 1)
|
||||||
|
|
||||||
|
// add sign(d) * 0.5 if sign(d) < 0 else sign(d) * 0.4
|
||||||
|
if ret.value.Sign() < 0 {
|
||||||
|
ret.value.Sub(ret.value, fiveInt)
|
||||||
|
} else {
|
||||||
|
ret.value.Add(ret.value, fourInt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// floor for positive numbers, ceil for negative numbers
|
||||||
|
_, m := ret.value.DivMod(ret.value, tenInt, new(big.Int))
|
||||||
|
ret.exp++
|
||||||
|
if ret.value.Sign() < 0 && m.Cmp(zeroInt) != 0 {
|
||||||
|
ret.value.Add(ret.value, oneInt)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
// RoundCeil rounds the decimal towards +infinity.
|
// RoundCeil rounds the decimal towards +infinity.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
|
|
135
decimal_test.go
135
decimal_test.go
|
@ -3647,3 +3647,138 @@ func ExampleNewFromFloat() {
|
||||||
//0.123123123123123
|
//0.123123123123123
|
||||||
//-10000000000000
|
//-10000000000000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDecimal_RoundHalfUp(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
d Decimal
|
||||||
|
places int32
|
||||||
|
want Decimal
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "550",
|
||||||
|
d: NewFromInt(550),
|
||||||
|
places: -2,
|
||||||
|
want: NewFromInt(600),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "545",
|
||||||
|
d: NewFromInt(545),
|
||||||
|
places: -2,
|
||||||
|
want: NewFromInt(500),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "500",
|
||||||
|
d: NewFromInt(500),
|
||||||
|
places: -2,
|
||||||
|
want: NewFromInt(500),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "1.1001",
|
||||||
|
d: NewFromFloat(1.1001),
|
||||||
|
places: 2,
|
||||||
|
want: NewFromFloat(1.10),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "-1.454",
|
||||||
|
d: NewFromFloat(-1.454),
|
||||||
|
places: 1,
|
||||||
|
want: NewFromFloat(-1.4),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "-1.464",
|
||||||
|
d: NewFromFloat(-1.464),
|
||||||
|
places: 1,
|
||||||
|
want: NewFromFloat(-1.5),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := tt.d.RoundHalfUp(tt.places); !got.Equal(tt.want) {
|
||||||
|
t.Errorf("RoundHalfUp() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDecimal_RoundHalfDown(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
d Decimal
|
||||||
|
places int32
|
||||||
|
want Decimal
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "550",
|
||||||
|
d: NewFromInt(550),
|
||||||
|
places: -2,
|
||||||
|
want: NewFromInt(500),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "560",
|
||||||
|
d: NewFromInt(560),
|
||||||
|
places: -2,
|
||||||
|
want: NewFromInt(600),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "500",
|
||||||
|
d: NewFromInt(500),
|
||||||
|
places: -2,
|
||||||
|
want: NewFromInt(500),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "1.1001",
|
||||||
|
d: NewFromFloat(1.1001),
|
||||||
|
places: 2,
|
||||||
|
want: NewFromFloat(1.10),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "-1.454",
|
||||||
|
d: NewFromFloat(-1.454),
|
||||||
|
places: 1,
|
||||||
|
want: NewFromFloat(-1.5),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "-1.444",
|
||||||
|
d: NewFromFloat(-1.444),
|
||||||
|
places: 1,
|
||||||
|
want: NewFromFloat(-1.4),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := tt.d.RoundHalfDown(tt.places); !got.Equal(tt.want) {
|
||||||
|
t.Errorf("RoundHalfDown() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDecimal_RoundHalfTowardZero(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
d Decimal
|
||||||
|
places int32
|
||||||
|
want Decimal
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "5.45",
|
||||||
|
d: NewFromFloat(5.45),
|
||||||
|
places: 1,
|
||||||
|
want: NewFromFloat(5.4),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "545",
|
||||||
|
d: NewFromInt(545),
|
||||||
|
places: -1,
|
||||||
|
want: NewFromInt(540),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := tt.d.RoundHalfTowardZero(tt.places); !got.Equal(tt.want) {
|
||||||
|
t.Errorf("RoundHalfDown() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue