From dae801456b637aaaf2598f3c898656aaf7b108fe Mon Sep 17 00:00:00 2001 From: Everett Date: Mon, 7 Oct 2024 22:21:40 +0800 Subject: [PATCH] add Round: returns the float32/float64 of rounding half away from the specified precision add Truncate: returns the float32/float64 of the specified precision --- README.md | 34 ++++++++++++++++++++++++++++++ math.go | 30 ++++++++++++++++++++++++++ math_example_test.go | 50 ++++++++++++++++++++++++++++++++++++++++++++ math_test.go | 50 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 164 insertions(+) diff --git a/README.md b/README.md index 73c33223..0592cd1a 100644 --- a/README.md +++ b/README.md @@ -1449,6 +1449,40 @@ mean := lo.MeanBy([]float64{}, mapper) // 0 ``` +### Round + +Round returns the float32/float64 of rounding half away from the specified precision. + +Precision must be between 0 and 15, if it is empty or exceeds the range, default value is 3 + +```go +f := Truncate(1.23456) +// 1.235 + +f := Truncate(1.23456, 4) +// 1.2346 + +f := Truncate(1.23456, 7) +// 1.23456 +``` + +### Truncate + +Truncate returns the float32/float64 of the specified precision. + +Precision must be between 0 and 15, if it is empty or exceeds the range, default value is 3 + +```go +f := Truncate(1.23456) +// 1.234 + +f := Truncate(1.23456, 4) +// 1.2345 + +f := Truncate(1.23456, 7) +// 1.23456 +``` + ### RandomString Returns a random string of the specified length and made of the specified charset. diff --git a/math.go b/math.go index 7a18ca62..cb6c42d9 100644 --- a/math.go +++ b/math.go @@ -1,7 +1,10 @@ package lo import ( + "fmt" "github.com/samber/lo/internal/constraints" + "math" + "strconv" ) // Range creates an array of numbers (positive and/or negative) with given length. @@ -104,3 +107,30 @@ func MeanBy[T any, R constraints.Float | constraints.Integer](collection []T, it var sum = SumBy(collection, iteratee) return sum / length } + +// Round returns the float32/float64 of rounding half away from the specified precision +func Round[T float64 | float32](f T, n ...int) T { + var nn = 3 + if len(n) > 0 { + if n[0] >= 0 && n[0] <= 15 { + nn = n[0] + } + } + r, _ := strconv.ParseFloat(fmt.Sprintf("%.*f", nn, f), 64) + return T(r) +} + +// Truncate returns the float32/float64 of the specified precision +func Truncate[T float64 | float32](f T, n ...int) T { + var nn = 3 + if len(n) > 0 { + nn = n[0] + if n[0] >= 0 && n[0] <= 15 { + nn = n[0] + } + } + pow10N := math.Pow10(nn) + integer, fractional := math.Modf(float64(f)) + r, _ := strconv.ParseFloat(fmt.Sprintf("%.*f", nn, integer+math.Trunc(fractional*pow10N)/pow10N), 64) + return T(r) +} diff --git a/math_example_test.go b/math_example_test.go index e71a9b79..6e8bc4c8 100644 --- a/math_example_test.go +++ b/math_example_test.go @@ -84,3 +84,53 @@ func ExampleMeanBy() { fmt.Printf("%v", result) } + +func ExampleRound() { + result1 := Round(1.23456) + result2 := Round(1.23456, 2) + result3 := Round(1.23456, 3) + result4 := Round(1.23456, 7) + result5 := Round(1.234999999999999, 15) + result6 := Round(1.234999999999999, 7) + result7 := Round(1.235, 14) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + fmt.Printf("%v\n", result5) + fmt.Printf("%v\n", result6) + fmt.Printf("%v\n", result7) + + // Output: + // 1.235 + // 1.23 + // 1.235 + // 1.23456 + // 1.234999999999999 + // 1.235 + // 1.235 +} + +func ExampleTruncate() { + result1 := Truncate(1.23456) + result2 := Truncate(1.23456, 2) + result3 := Truncate(1.23456, 4) + result4 := Truncate(1.23456, 7) + result5 := Truncate(1.2349999999999999, 15) + result6 := Truncate(1.2349999999999999, 7) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + fmt.Printf("%v\n", result5) + fmt.Printf("%v\n", result6) + // Output: + // 1.234 + // 1.23 + // 1.2345 + // 1.23456 + // 1.234999999999999 + // 1.2349999 +} diff --git a/math_test.go b/math_test.go index 8e5efeda..7dba4fba 100644 --- a/math_test.go +++ b/math_test.go @@ -127,3 +127,53 @@ func TestMeanBy(t *testing.T) { is.Equal(result3, uint32(3)) is.Equal(result4, uint32(0)) } + +func TestRound(t *testing.T) { + t.Parallel() + is := assert.New(t) + + result1 := Round(0.086990000031, 5) + result2 := Round(1.23456) + result3 := Round(1.23456, 2) + result4 := Round(1.23456, 3) + result5 := Round(1.23456, 7) + result6 := Round(1.23456, 15) + result7 := Round(1.23456789, 7) + result8 := Round(1.23456, 0) + result9 := Round(1.00000000001, 5) + + is.Equal(result1, 0.08699) + is.Equal(result2, 1.235) + is.Equal(result3, 1.23) + is.Equal(result4, 1.235) + is.Equal(result5, 1.23456) + is.Equal(result6, 1.23456) + is.Equal(result7, 1.2345679) + is.Equal(result8, 1.0) + is.Equal(result9, 1.0) +} + +func TestTruncate(t *testing.T) { + t.Parallel() + is := assert.New(t) + + result1 := Truncate(0.086990000031, 5) + result2 := Truncate(1.23456) + result3 := Truncate(1.23456, 2) + result4 := Truncate(1.23456, 3) + result5 := Truncate(1.23456, 7) + result6 := Truncate(1.23456, 15) + result7 := Truncate(1.23456789, 7) + result8 := Truncate(1.23456, 0) + result9 := Truncate(1.00000000001, 5) + + is.Equal(result1, 0.08699) + is.Equal(result2, 1.234) + is.Equal(result3, 1.23) + is.Equal(result4, 1.234) + is.Equal(result5, 1.23456) + is.Equal(result6, 1.23456) + is.Equal(result7, 1.2345678) + is.Equal(result8, 1.0) + is.Equal(result9, 1.0) +}