Skip to content

Commit

Permalink
feat: add comparison utilities (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
quagmt authored Jan 4, 2025
1 parent fe59b7f commit c313c7c
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 32 deletions.
43 changes: 43 additions & 0 deletions decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,49 @@ func (d Decimal) Equal(e Decimal) bool {
return d.Cmp(e) == 0
}

// LessThan reports whether d < e.
func (d Decimal) LessThan(e Decimal) bool {
return d.Cmp(e) == -1
}

// LessThanOrEqual reports whether d <= e.
func (d Decimal) LessThanOrEqual(e Decimal) bool {
return d.Cmp(e) <= 0
}

// GreaterThan reports whether d > e.
func (d Decimal) GreaterThan(e Decimal) bool {
return d.Cmp(e) == 1
}

// GreaterThanOrEqual reports whether d >= e.
func (d Decimal) GreaterThanOrEqual(e Decimal) bool {
return d.Cmp(e) >= 0
}

// Max returns the maximum decimal from the list of decimals.
func Max(a Decimal, b ...Decimal) Decimal {
result := a
for _, v := range b {
if v.GreaterThan(result) {
result = v
}
}

return result
}

func Min(a Decimal, b ...Decimal) Decimal {
result := a
for _, v := range b {
if v.LessThan(result) {
result = v
}
}

return result
}

func (d Decimal) cmpDecSameSign(e Decimal) int {
result, err := tryCmpU128(d, e)
if err == nil {
Expand Down
125 changes: 93 additions & 32 deletions decimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1275,36 +1275,40 @@ func TestCmp(t *testing.T) {
}
}

func TestEqual(t *testing.T) {
func TestComparisionUtils(t *testing.T) {
testcases := []struct {
a, b string
want bool
a, b string
wantEqual bool
wantLT bool
wantLTE bool
wantGT bool
wantGTE bool
}{
{"1234567890123456789", "0", false},
{"123.123", "-123.123", false},
{"-123.123", "123.123", false},
{"-123.123", "-123.123", true},
{"-123.123", "-123.1234567890123456789", false},
{"123.123", "123.1234567890123456789", false},
{"123.123", "123.1230000000000000001", false},
{"-123.123", "-123.1230000000000000001", false},
{"123.1230000000000000002", "123.1230000000000000001", false},
{"-123.1230000000000000002", "-123.1230000000000000001", false},
{"123.1230000000000000002", "123.123000000001", false},
{"-123.1230000000000000002", "-123.123000000001", false},
{"123.123", "123.1230000", true},
{"123.101", "123.1001", false},
{"1000000000000000000000000.1234567890123456789", "1.1234567890123456789", false},
{"-1000000000000000000000000.1234567890123456789", "1.1234567890123456789", false},
{"-1000000000000000000000000.1234567890123456789", "-1.1234567890123456789", false},
{"1000000000000000000000000.1234567890123456789", "1000000000000000000000000.1234567890123456789", true},
{"-1000000000000000000000000.1234567890123456789", "-1000000000000000000000000.1234567890123456789", true},
{"1000000000000000000000000.1234567890123456789", "1000000000000000000000000.1234567890123456788", false},
{"-1000000000000000000000000.1234567890123456789", "-1000000000000000000000000.1234567890123456788", false},
{"1000000000000000000000000.12345678901234", "1000000000000000000000000.1234567890123456788", false},
{"-1000000000000000000000000.12345678901234", "-1000000000000000000000000.1234567890123456788", false},
{"1000000000000000000000000.1234567890123456788", "1000000000000000000000000.12345678901234", false},
{"-1000000000000000000000000.1234567890123456788", "-1000000000000000000000000.12345678901234", false},
{"1234567890123456789", "0", false, false, false, true, true},
{"123.123", "-123.123", false, false, false, true, true},
{"-123.123", "123.123", false, true, true, false, false},
{"-123.123", "-123.123", true, false, true, false, true},
{"-123.123", "-123.1234567890123456789", false, false, false, true, true},
{"123.123", "123.1234567890123456789", false, true, true, false, false},
{"123.123", "123.1230000000000000001", false, true, true, false, false},
{"-123.123", "-123.1230000000000000001", false, false, false, true, true},
{"123.1230000000000000002", "123.1230000000000000001", false, false, false, true, true},
{"-123.1230000000000000002", "-123.1230000000000000001", false, true, true, false, false},
{"123.1230000000000000002", "123.123000000001", false, true, true, false, false},
{"-123.1230000000000000002", "-123.123000000001", false, false, false, true, true},
{"123.123", "123.1230000", true, false, true, false, true},
{"123.101", "123.1001", false, false, false, true, true},
{"1000000000000000000000000.1234567890123456789", "1.1234567890123456789", false, false, false, true, true},
{"-1000000000000000000000000.1234567890123456789", "1.1234567890123456789", false, true, true, false, false},
{"-1000000000000000000000000.1234567890123456789", "-1.1234567890123456789", false, true, true, false, false},
{"1000000000000000000000000.1234567890123456789", "1000000000000000000000000.1234567890123456789", true, false, true, false, true},
{"-1000000000000000000000000.1234567890123456789", "-1000000000000000000000000.1234567890123456789", true, false, true, false, true},
{"1000000000000000000000000.1234567890123456789", "1000000000000000000000000.1234567890123456788", false, false, false, true, true},
{"-1000000000000000000000000.1234567890123456789", "-1000000000000000000000000.1234567890123456788", false, true, true, false, false},
{"1000000000000000000000000.12345678901234", "1000000000000000000000000.1234567890123456788", false, true, true, false, false},
{"-1000000000000000000000000.12345678901234", "-1000000000000000000000000.1234567890123456788", false, false, false, true, true},
{"1000000000000000000000000.1234567890123456788", "1000000000000000000000000.12345678901234", false, false, false, true, true},
{"-1000000000000000000000000.1234567890123456788", "-1000000000000000000000000.12345678901234", false, true, true, false, false},
}

for _, tc := range testcases {
Expand All @@ -1315,19 +1319,76 @@ func TestEqual(t *testing.T) {
b, err := Parse(tc.b)
require.NoError(t, err)

c := a.Equal(b)
require.Equal(t, tc.want, c)

// compare with shopspring/decimal
aa := decimal.RequireFromString(tc.a)
bb := decimal.RequireFromString(tc.b)

// test equal
c := a.Equal(b)
cc := aa.Equal(bb)
require.Equal(t, tc.wantEqual, c)
require.Equal(t, cc, c)

// test less than
c = a.LessThan(b)
cc = aa.LessThan(bb)
require.Equal(t, tc.wantLT, c)
require.Equal(t, cc, c)

// test less than or equal
c = a.LessThanOrEqual(b)
cc = aa.LessThanOrEqual(bb)
require.Equal(t, tc.wantLTE, c)
require.Equal(t, cc, c)

// test greater than
c = a.GreaterThan(b)
cc = aa.GreaterThan(bb)
require.Equal(t, tc.wantGT, c)
require.Equal(t, cc, c)

// test greater than or equal
c = a.GreaterThanOrEqual(b)
cc = aa.GreaterThanOrEqual(bb)
require.Equal(t, tc.wantGTE, c)
require.Equal(t, cc, c)
})
}
}

func TestMaxMin(t *testing.T) {
testcases := []struct {
list []string
wantMax string
wantMin string
}{
{[]string{"1234567890123456789", "0", "1234567890123456789", "1234567890123456789"}, "1234567890123456789", "0"},
{[]string{"123.123", "-123.123", "123.123", "-123.123"}, "123.123", "-123.123"},
{[]string{"-1235.123124235235", "0.11", "5345.29809824", "-6465465.45646"}, "5345.29809824", "-6465465.45646"},
{[]string{"1.123", "2.235"}, "2.235", "1.123"},
{[]string{"-1.123", "-2.235"}, "-1.123", "-2.235"},
{[]string{"1.123"}, "1.123", "1.123"},
}

for _, tc := range testcases {
t.Run(fmt.Sprintf("%v", tc.list), func(t *testing.T) {
list := make([]Decimal, len(tc.list))
for i, s := range tc.list {
d, err := Parse(s)
require.NoError(t, err)
list[i] = d
}

// test max
expectedMax := Max(list[0], list[1:]...)
require.Equal(t, tc.wantMax, expectedMax.String())

// test min
expectedMin := Min(list[0], list[1:]...)
require.Equal(t, tc.wantMin, expectedMin.String())
})
}
}

func TestCmpWithDifferentPrecision(t *testing.T) {
testcases := []struct {
a1, a2, b string
Expand Down
52 changes: 52 additions & 0 deletions doc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,58 @@ func ExampleDecimal_Cmp() {
// 1
}

func ExampleDecimal_LessThan() {
fmt.Println(MustParse("1.23").LessThan(MustParse("4.12475")))
fmt.Println(MustParse("1.23").LessThan(MustParse("1.23")))
fmt.Println(MustParse("1.23").LessThan(MustParse("0.12475")))
// Output:
// true
// false
// false
}

func ExampleDecimal_LessThanOrEqual() {
fmt.Println(MustParse("1.23").LessThanOrEqual(MustParse("4.12475")))
fmt.Println(MustParse("1.23").LessThanOrEqual(MustParse("1.23")))
fmt.Println(MustParse("1.23").LessThanOrEqual(MustParse("0.12475")))
// Output:
// true
// true
// false
}

func ExampleDecimal_GreaterThan() {
fmt.Println(MustParse("1.23").GreaterThan(MustParse("4.12475")))
fmt.Println(MustParse("1.23").GreaterThan(MustParse("1.23")))
fmt.Println(MustParse("1.23").GreaterThan(MustParse("0.12475")))
// Output:
// false
// false
// true
}

func ExampleDecimal_GreaterThanOrEqual() {
fmt.Println(MustParse("1.23").GreaterThanOrEqual(MustParse("4.12475")))
fmt.Println(MustParse("1.23").GreaterThanOrEqual(MustParse("1.23")))
fmt.Println(MustParse("1.23").GreaterThanOrEqual(MustParse("0.12475")))
// Output:
// false
// true
// true
}

func ExampleMax() {
fmt.Println(Max(MustParse("1.23"), MustParse("4.12475")))
// Output:
// 4.12475
}

func ExampleMin() {
fmt.Println(Min(MustParse("1.23"), MustParse("4.12475")))
// Output:
// 1.23
}

func ExampleDecimal_Equal() {
fmt.Println(MustParse("1.123").Equal(MustParse("-1.123")))
fmt.Println(MustParse("1.123").Equal(MustParse("1.1230000")))
Expand Down

0 comments on commit c313c7c

Please sign in to comment.