Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding RoundUp #194

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions decimal.go
Expand Up @@ -902,6 +902,18 @@ func (d Decimal) RoundBank(places int32) Decimal {
return round
}

// RoundUp rounds decimal number towards positive infinite
// (1.1).RoundUp(0) => 1
// (1.52).RoundUp(1) => 1.6
// (1.1001).RoundUp(2) => 1.11
func (d Decimal) RoundUp(places int32) Decimal {
factor := NewFromFloat(10).Pow(NewFromInt(int64(places)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decimal Pow is not a high-performance method. I have benchmarked them before but not have results here. You can try to benchmark it.

How about

factor := NewFromFloat(math.Pow(10, float64(-places))

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Great suggestion, I'll try it out.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using math.Pow:

BenchmarkDecimal_RoundUp-8                            	  799142	      1522 ns/op

using Decimal.Pow

BenchmarkDecimal_RoundUp-8                            	  255872	      4411 ns/op

I'll update the PR with your suggestion.

m := d.Mul(factor)
n := m.Ceil()
o := n.Div(factor)
return o
}

// RoundCash aka Cash/Penny/öre rounding rounds decimal to a specific
// interval. The amount payable for a cash transaction is rounded to the nearest
// multiple of the minimum currency unit available. The following intervals are
Expand Down
88 changes: 88 additions & 0 deletions decimal_test.go
Expand Up @@ -994,6 +994,94 @@ func TestDecimal_RoundAndStringFixed(t *testing.T) {
}
}

func TestDecimal_RoundUpAndStringFixed(t *testing.T) {
type testData struct {
input string
places int32
expected string
expectedFixed string
}
tests := []testData{
{"1.454", 0, "2", ""},
{"1.454", 1, "1.5", ""},
{"1.454", 2, "1.46", ""},
{"1.454", 3, "1.454", ""},
{"1.454", 4, "1.454", "1.4540"},
{"1.454", 5, "1.454", "1.45400"},
{"1.554", 0, "2", ""},
{"1.554", 1, "1.6", ""},
{"1.554", 2, "1.56", ""},
{"0.554", 0, "1", ""},
{"0.454", 0, "1", ""},
{"0.454", 5, "0.454", "0.45400"},
{"0", 0, "0", ""},
{"0", 1, "0", "0.0"},
{"0", 2, "0", "0.00"},
{"0", -1, "0", ""},
{"5", 2, "5", "5.00"},
{"5", 1, "5", "5.0"},
{"5", 0, "5", ""},
{"500", 2, "500", "500.00"},
{"545", -1, "550", ""},
{"545", -2, "600", ""},
{"545", -3, "1000", ""},
{"545", -4, "10000", ""},
{"499", -3, "1000", ""},
{"499", -4, "10000", ""},
{"1.1001", 2, "1.11", ""},
{"-1.454", 0, "-1", ""},
{"-1.454", 1, "-1.4", ""},
{"-1.454", 2, "-1.45", ""},
{"-1.454", 3, "-1.454", ""},
{"-1.454", 4, "-1.454", "-1.4540"},
{"-1.454", 5, "-1.454", "-1.45400"},
{"-1.554", 0, "-1", ""},
{"-1.554", 1, "-1.5", ""},
{"-1.554", 2, "-1.55", ""},
{"-0.554", 0, "0", ""},
{"-0.454", 0, "0", ""},
{"-0.454", 5, "-0.454", "-0.45400"},
{"-5", 2, "-5", "-5.00"},
{"-5", 1, "-5", "-5.0"},
{"-5", 0, "-5", ""},
{"-500", 2, "-500", "-500.00"},
{"-545", -1, "-540", ""},
{"-545", -2, "-500", ""},
{"-545", -3, "0", ""},
{"-545", -4, "0", ""},
{"-499", -3, "0", ""},
{"-499", -4, "0", ""},
}

for _, test := range tests {
d, err := NewFromString(test.input)
if err != nil {
panic(err)
}

// test Round
expected, err := NewFromString(test.expected)
if err != nil {
panic(err)
}
got := d.RoundUp(test.places)
if !got.Equal(expected) {
t.Errorf("Rounding Up %s to %d places, got %s, expected %s",
d, test.places, got, expected)
}

// test StringFixed
if test.expectedFixed == "" {
test.expectedFixed = test.expected
}
gotStr := got.StringFixed(test.places)
if gotStr != test.expectedFixed {
t.Errorf("(%s).StringFixed(%d): got %s, expected %s",
d, test.places, gotStr, test.expectedFixed)
}
}
}

func TestDecimal_BankRoundAndStringFixed(t *testing.T) {
type testData struct {
input string
Expand Down