From cf80d21881039b41bdfbed1932d161e211834077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=85=89=E6=98=A5?= Date: Wed, 20 Jul 2022 15:47:20 +0800 Subject: [PATCH] - update --- README.md | 21 ++++++++ big.go | 15 ++++++ big_new.go | 29 +++++++++++ big_operation.go | 29 +++++++++++ big_output.go | 24 +++++++++ big_test.go | 97 +++++++++++++++++++++++++++++++++++++ calculation.go | 21 ++++++++ calculation_test.go | 13 +++++ go.mod | 4 +- go.sum | 4 +- godecimal.go | 115 -------------------------------------------- godecimal_test.go | 16 ------ math.go | 38 +++++++++++++++ math_test.go | 26 ++++++++++ version.go | 2 +- 15 files changed, 318 insertions(+), 136 deletions(-) create mode 100644 README.md create mode 100644 big.go create mode 100644 big_new.go create mode 100644 big_operation.go create mode 100644 big_output.go create mode 100644 big_test.go create mode 100644 calculation.go create mode 100644 calculation_test.go delete mode 100644 godecimal.go delete mode 100644 godecimal_test.go create mode 100644 math.go create mode 100644 math_test.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..3e3b476 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +

+Golang Decimal +

+ +📦 Golang Decimal + +[comment]: <> (go) +[![godoc](https://pkg.go.dev/badge/github.com/dtapps/godecimal?status.svg)](https://pkg.go.dev/github.com/dtapps/godecimal) +[![goproxy.cn](https://goproxy.cn/stats/github.com/dtapps/godecimal/badges/download-count.svg)](https://goproxy.cn/stats/github.com/dtapps/godecimal) +[![goreportcard.com](https://goreportcard.com/badge/github.com/dtapps/godecimal)](https://goreportcard.com/report/github.com/dtapps/godecimal) +[![deps.dev](https://img.shields.io/badge/deps-go-red.svg)](https://deps.dev/go/github.com/dtapps/godecimal) + +#### 安装使用 + +```go +go get -v -u github.com/dtapps/godecimal + +import ( + "github.com/dtapps/godecimal" +) +``` \ No newline at end of file diff --git a/big.go b/big.go new file mode 100644 index 0000000..3a21647 --- /dev/null +++ b/big.go @@ -0,0 +1,15 @@ +package godecimal + +import ( + "math/big" +) + +type Decimal struct { + floatValue *big.Float +} + +func New() Decimal { + return Decimal{ + floatValue: new(big.Float), + } +} diff --git a/big_new.go b/big_new.go new file mode 100644 index 0000000..d9ed234 --- /dev/null +++ b/big_new.go @@ -0,0 +1,29 @@ +package godecimal + +// NewString 从字符串创建 +func NewString(s string) Decimal { + d := New() + d.floatValue.SetString(s) + return d +} + +// NewFloat 从浮点数创建 +func NewFloat(f float64) Decimal { + d := New() + d.floatValue.SetFloat64(f) + return d +} + +// NewInt 从整数创建 +func NewInt(i int64) Decimal { + d := New() + d.floatValue.SetInt64(i) + return d +} + +// NewUint 从无符合整数创建 +func NewUint(i uint64) Decimal { + d := New() + d.floatValue.SetUint64(i) + return d +} diff --git a/big_operation.go b/big_operation.go new file mode 100644 index 0000000..a01c05a --- /dev/null +++ b/big_operation.go @@ -0,0 +1,29 @@ +package godecimal + +// Add 加 (d+d2) +func (d Decimal) Add(d2 Decimal) Decimal { + mul := New() + mul.floatValue.Add(d.floatValue, d2.floatValue) + return mul +} + +// Sub 减 (d-d2) +func (d Decimal) Sub(d2 Decimal) Decimal { + mul := New() + mul.floatValue.Sub(d.floatValue, d2.floatValue) + return mul +} + +// Mul 乘 (d*d2) +func (d Decimal) Mul(d2 Decimal) Decimal { + mul := New() + mul.floatValue.Mul(d.floatValue, d2.floatValue) + return mul +} + +// Quo 除 (d/d2) +func (d Decimal) Quo(d2 Decimal) Decimal { + mul := New() + mul.floatValue.Quo(d.floatValue, d2.floatValue) + return mul +} diff --git a/big_output.go b/big_output.go new file mode 100644 index 0000000..57f0a9a --- /dev/null +++ b/big_output.go @@ -0,0 +1,24 @@ +package godecimal + +import ( + "math/big" +) + +// String 输出 string +func (d Decimal) String() string { + return d.floatValue.String() +} + +// Float64 输出 float64 +func (d Decimal) Float64() float64 { + rat, _ := new(big.Rat).SetString(d.String()) + f, _ := rat.Float64() + return f +} + +// MoneyFloat64 货币 float64 +func (d Decimal) MoneyFloat64() float64 { + rat, _ := new(big.Rat).SetString(d.floatValue.Text('f', 2)) + f, _ := rat.Float64() + return f +} diff --git a/big_test.go b/big_test.go new file mode 100644 index 0000000..9dc4130 --- /dev/null +++ b/big_test.go @@ -0,0 +1,97 @@ +package godecimal + +import ( + "fmt" + "github.com/shopspring/decimal" + "math/big" + "reflect" + "testing" +) + +func TestNew(t *testing.T) { + + priceString := NewString("100") + t.Log("从字符串创建:", priceString) + + priceFloat := NewFloat(0.20) + t.Log("从浮点数创建:", priceFloat) + + priceInt := NewInt(300) + t.Log("从整数创建:", priceInt) + + priceUint := NewUint(400) + t.Log("从无符合整数创建:", priceUint) + + t.Log("加:", priceString.Add(priceFloat), reflect.TypeOf(priceString)) + t.Log("减", priceString.Sub(priceFloat), reflect.TypeOf(priceString)) + t.Log("乘:", priceString.Mul(priceFloat), reflect.TypeOf(priceString)) + t.Log("除:", priceString.Quo(priceFloat), reflect.TypeOf(priceString)) +} + +// https://www.itranslater.com/qa/details/2582643503239005184 +// https://stackoverflow.com/questions/18390266/how-can-we-truncate-float64-type-to-a-particular-precision +func TestOperation(t *testing.T) { + + a1 := NewFloat(0.1890) + t.Log("a1:", a1) + + a2 := NewFloat(0.50) + t.Log("a2:", a2) + + t.Log("a1+a2:", a1.Add(a2), a1.Add(a2).String(), a1.Add(a2).Float64(), reflect.TypeOf(a1.Add(a2).Float64()), a1.Add(a2).MoneyFloat64(), reflect.TypeOf(a1.Add(a2).MoneyFloat64())) + t.Log("a1-a2:", a1.Sub(a2), a1.Sub(a2).String(), a1.Sub(a2).Float64(), reflect.TypeOf(a1.Sub(a2).Float64()), a1.Sub(a2).MoneyFloat64(), reflect.TypeOf(a1.Sub(a2).MoneyFloat64())) + t.Log("a1*a2:", a1.Mul(a2), a1.Mul(a2).String(), a1.Mul(a2).Float64(), reflect.TypeOf(a1.Mul(a2).Float64()), a1.Mul(a2).MoneyFloat64(), reflect.TypeOf(a1.Mul(a2).MoneyFloat64())) + t.Log("a1/a2:", a1.Quo(a2), a1.Quo(a2).String(), a1.Quo(a2).Float64(), reflect.TypeOf(a1.Quo(a2).Float64()), a1.Quo(a2).MoneyFloat64(), reflect.TypeOf(a1.Quo(a2).MoneyFloat64())) + + a3 := NewFloat(.035) + t.Log("a3:", a3) + + a4 := NewFloat(.08875) + t.Log("a4:", a4) + + t.Log("a3+a4:", a3.Add(a4), a3.Add(a4).String(), a3.Add(a4).Float64(), reflect.TypeOf(a3.Add(a4).Float64()), a3.Add(a4).MoneyFloat64(), reflect.TypeOf(a3.Add(a4).MoneyFloat64())) + t.Log("a3-a4:", a3.Sub(a4), a3.Sub(a4).String(), a3.Sub(a4).Float64(), reflect.TypeOf(a3.Sub(a4).Float64()), a3.Sub(a4).MoneyFloat64(), reflect.TypeOf(a3.Sub(a4).MoneyFloat64())) + t.Log("a3*a4:", a3.Mul(a4), a3.Mul(a4).String(), a3.Mul(a4).Float64(), reflect.TypeOf(a3.Mul(a4).Float64()), a3.Mul(a4).MoneyFloat64(), reflect.TypeOf(a3.Mul(a4).MoneyFloat64())) + t.Log("a3/a4:", a3.Quo(a4), a3.Quo(a4).String(), a3.Quo(a4).Float64(), reflect.TypeOf(a3.Quo(a4).Float64()), a3.Quo(a4).MoneyFloat64(), reflect.TypeOf(a3.Quo(a4).MoneyFloat64())) +} + +func TestDecimal1(t *testing.T) { + price, err := decimal.NewFromString("136.02") + if err != nil { + panic(err) + } + + quantity := decimal.NewFromInt(3) + + fee, _ := decimal.NewFromString(".035") + taxRate, _ := decimal.NewFromString(".08875") + + subtotal := price.Mul(quantity) + + preTax := subtotal.Mul(fee.Add(decimal.NewFromFloat(1))) + + total := preTax.Mul(taxRate.Add(decimal.NewFromFloat(1))) + + fmt.Println("Subtotal:", subtotal, reflect.TypeOf(subtotal)) // Subtotal: 408.06 + fmt.Println("Pre-tax:", preTax, reflect.TypeOf(preTax)) // Pre-tax: 422.3421 + fmt.Println("Taxes:", total.Sub(preTax)) // Taxes: 37.482861375 + fmt.Println("Total:", total) // Total: 459.824961375 + fmt.Println("Tax rate:", total.Sub(preTax).Div(preTax)) // Tax rate: 0.08875 + + t.Log(total.String()) + t.Log(total.Float64()) + t.Log(total.Floor()) + +} + +func Test3(t *testing.T) { + + var x1, y1 float64 = 10, 3 + z1 := x1 / y1 + t.Log(x1, y1, z1) + + x2, y2 := big.NewFloat(10), big.NewFloat(3) + z2 := new(big.Float).Quo(x2, y2) + t.Log(x2, y2, z2) + +} diff --git a/calculation.go b/calculation.go new file mode 100644 index 0000000..51abbf6 --- /dev/null +++ b/calculation.go @@ -0,0 +1,21 @@ +package godecimal + +// Float64Add 加 (f1+f2) +func Float64Add(f1, f2 float64) float64 { + return NewFloat(f1).Add(NewFloat(f2)).Float64() +} + +// Float64Sub 减 (f1-f2) +func Float64Sub(f1, f2 float64) float64 { + return NewFloat(f1).Sub(NewFloat(f2)).Float64() +} + +// Float64Mul 乘 (f1*f2) +func Float64Mul(f1, f2 float64) float64 { + return NewFloat(f1).Mul(NewFloat(f2)).Float64() +} + +// Float64Quo 除 (f1/f2) +func Float64Quo(f1, f2 float64) float64 { + return NewFloat(f1).Quo(NewFloat(f2)).Float64() +} diff --git a/calculation_test.go b/calculation_test.go new file mode 100644 index 0000000..43f56f3 --- /dev/null +++ b/calculation_test.go @@ -0,0 +1,13 @@ +package godecimal + +import ( + "reflect" + "testing" +) + +func TestCalculation(t *testing.T) { + t.Log("加:", Float64Add(10, 3), reflect.TypeOf(Float64Add(10, 3))) + t.Log("减", Float64Sub(10, 3), reflect.TypeOf(Float64Sub(10, 3))) + t.Log("乘:", Float64Mul(10, 3), reflect.TypeOf(Float64Mul(10, 3))) + t.Log("除:", Float64Quo(10, 3), reflect.TypeOf(Float64Quo(10, 3))) +} diff --git a/go.mod b/go.mod index ec068e7..1995b8a 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ -module go.dtapp.net/godecimal +module github.com/dtapps/godecimal go 1.18 -require go.dtapp.net/gostring v1.0.3 +require github.com/shopspring/decimal v1.3.1 diff --git a/go.sum b/go.sum index 5d8b1b3..3289fec 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,2 @@ -go.dtapp.net/gostring v1.0.3 h1:KSOq4D77/g5yZN/bqWfZ0kOOaPr/P1240vg03+XdENI= -go.dtapp.net/gostring v1.0.3/go.mod h1:+ggrOvgQDQturi1QGsXEpyRN/ZPoRDaqhMujIk5lrgQ= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= diff --git a/godecimal.go b/godecimal.go deleted file mode 100644 index fec8758..0000000 --- a/godecimal.go +++ /dev/null @@ -1,115 +0,0 @@ -package godecimal - -import ( - "fmt" - "go.dtapp.net/gostring" - "math" - "strconv" -) - -// Decimal 四舍五入 -func Decimal(value float64) float64 { - value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64) - return value -} - -// Round 四舍五入 -func Round(f float64, n int) float64 { - n10 := math.Pow10(n) - return math.Trunc((f+0.5/n10)*n10) / n10 -} - -// RoundYInt64 四舍五入 -func RoundYInt64(y int64, n int) float64 { - return Round(float64(y/100), n) -} - -// RoundYString 四舍五入 -func RoundYString(y string, n int) float64 { - return Round(gostring.ToFloat64(y)/100, n) -} - -// Multiply 相乘 -func Multiply(y, x float64) float64 { - return Round(y*x, 2) -} - -// PddCouponAmount 优惠券金额 -func PddCouponAmount(y int64) float64 { - return Round(float64(y)/100, 2) -} - -// PddCouponProportion 拼多多佣金比率 -func PddCouponProportion(y int64) float64 { - return Round(float64(y)/10, 2) -} - -// PddGoodsOriginalPrice 拼多多商品原价 -func PddGoodsOriginalPrice(y int64) float64 { - return Round(float64(y)/100, 2) -} - -// PddGoodsPrice 拼多多商品券后价 -func PddGoodsPrice(y, x float64) float64 { - return Round(y-x, 2) -} - -// PddCommission 拼多多佣金 -func PddCommission(y, x float64) float64 { - return Round((y*x)/100, 2) -} - -// TbCouponAmount 淘宝优惠券金额 -func TbCouponAmount(y int64) float64 { - return Round(float64(y), 2) -} - -// TbCouponProportion 淘宝佣金比率 -func TbCouponProportion(y string) float64 { - return Round(gostring.ToFloat64(y)/100, 2) -} - -// TbGoodsOriginalPrice 淘宝商品原价 -func TbGoodsOriginalPrice(y string) float64 { - return Round(gostring.ToFloat64(y), 2) -} - -// TbGoodsPrice 淘宝商品券后价 -func TbGoodsPrice(y, x float64) float64 { - return Round(y-x, 2) -} - -// TbCommission 淘宝佣金 -func TbCommission(y, x float64) float64 { - return Round((y*x)/100, 2) -} - -// WmCouponAmount 小商店优惠券金额 -func WmCouponAmount(y string) float64 { - return Round(gostring.ToFloat64(y)/100, 2) -} - -// WmCouponProportion 小商店佣金比率 -func WmCouponProportion(y int64) float64 { - return Round(float64(y)/100, 2) -} - -// WmCommission 小商店佣金 -func WmCommission(y int64) float64 { - return Round(float64(y)/100, 2) -} - -// WmGoodsOriginalPrice 小商店商品原价 -func WmGoodsOriginalPrice(y int64) float64 { - return Round(float64(y)/100, 2) -} - -// WmGoodsPrice 小商店商品券后价 -func WmGoodsPrice(y int64) float64 { - return Round(float64(y)/100, 2) -} - -// JdCommission 京东佣金 -func JdCommission(y, x float64) float64 { - return Round((y*x)/100, 2) -} diff --git a/godecimal_test.go b/godecimal_test.go deleted file mode 100644 index f816c9e..0000000 --- a/godecimal_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package godecimal - -import ( - "testing" -) - -func TestDecimal(t *testing.T) { - t.Log(Decimal(2.3333)) -} - -func TestRound(t *testing.T) { - t.Log(Round(2.3333, 1)) - t.Log(Round(2.3333, 2)) - t.Log(Round(2.3333, 3)) - t.Log(Round(2.3333, 4)) -} diff --git a/math.go b/math.go new file mode 100644 index 0000000..7a3ac0b --- /dev/null +++ b/math.go @@ -0,0 +1,38 @@ +package godecimal + +import "math" + +// Abs 取绝对值 +func Abs(x float64) float64 { + return math.Abs(x) +} + +// Floor 向下取整 +func Floor(x float64) float64 { + return math.Floor(x) +} + +// Ceil 向上取整 +func Ceil(x float64) float64 { + return math.Ceil(x) +} + +// Round 就近取整 +func Round(x float64) float64 { + return math.Round(x) +} + +// RoundPoint 就近取整并保留小数点 +func RoundPoint(x float64) float64 { + return math.Round(x*100) / 100 +} + +// Max 取较大值 +func Max(x, y float64) float64 { + return math.Max(x, y) +} + +// Min 取较小值 +func Min(x, y float64) float64 { + return math.Min(x, y) +} diff --git a/math_test.go b/math_test.go new file mode 100644 index 0000000..0197d83 --- /dev/null +++ b/math_test.go @@ -0,0 +1,26 @@ +package godecimal + +import "testing" + +func TestMath(t *testing.T) { + t.Log(Abs(111)) + t.Log(Abs(-111)) + + t.Log(Floor(3.4)) + t.Log(Floor(3.5)) + + t.Log(Ceil(3.4)) + t.Log(Ceil(3.5)) + + t.Log(Round(3.4)) + t.Log(Round(3.5)) + + t.Log(RoundPoint(3.4)) + t.Log(RoundPoint(3.5)) + t.Log(RoundPoint(3.14)) + t.Log(RoundPoint(3.14159)) + + t.Log(Max(4, 3)) + + t.Log(Min(4, 3)) +} diff --git a/version.go b/version.go index c0b8aad..a29dd16 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package godecimal -const Version = "1.0.0" +const Version = "1.0.1"