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

feat: comparison utilities #35

Merged
merged 1 commit into from
Jan 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading