shopspring/decimal 使用教程
github.com/shopspring/decimal
是一个用于高精度十进制运算的 Go 语言库,特别适合需要避免浮点数精度问题的场景,比如金融计算。以下是对其使用方法的整理:
安装
在你的项目中引入该库:
go get github.com/shopspring/decimal
基本用法
创建 Decimal 实例
从字符串创建:
import "github.com/shopspring/decimal" d, err := decimal.NewFromString("123.456") if err != nil { panic(err) } fmt.Println(d) // 输出:123.456
从整数和浮点数创建:
d1 := decimal.NewFromInt(42) d2 := decimal.NewFromFloat(3.14) fmt.Println(d1, d2) // 输出:42 3.14
从整数部分和小数部分创建:
d := decimal.New(123456, -3) // 123.456 fmt.Println(d)
基本运算
加法:
d1 := decimal.NewFromInt(10) d2 := decimal.NewFromInt(20) result := d1.Add(d2) fmt.Println(result) // 输出:30
减法:
result := d1.Sub(d2) fmt.Println(result) // 输出:-10
乘法:
result := d1.Mul(d2) fmt.Println(result) // 输出:200
除法:
result := d2.Div(d1) fmt.Println(result) // 输出:2
求余:
result := d2.Mod(d1) fmt.Println(result) // 输出:0
比较操作
比较两个 Decimal 值:
比较结果有以下几种:
-1
:表示第一个值小于第二个值0
:表示两个值相等1
:表示第一个值大于第二个值
d1 := decimal.NewFromFloat(3.14) d2 := decimal.NewFromFloat(2.71) fmt.Println(d1.Cmp(d2)) // 输出:1 表示 d1 > d2
检查是否相等:
fmt.Println(d1.Equals(d2)) // 输出:false
检查是否大于、小于:
fmt.Println(d1.GreaterThan(d2)) // 输出:true fmt.Println(d1.LessThan(d2)) // 输出:false
精度控制
四舍五入:
d := decimal.NewFromFloat(3.14159) rounded := d.Round(2) fmt.Println(rounded) // 输出:3.14
设置小数位数:
truncated := d.Truncate(2) fmt.Println(truncated) // 输出:3.14
转换为其他类型
转换为字符串:
fmt.Println(d.String()) // 输出:3.14
转换为浮点数:
f, exact := d.Float64() fmt.Println(f, exact) // 输出:3.14159 true
转换为整数:
i := d.IntPart() fmt.Println(i) // 输出:3
高级特性
累积计算:
sum := decimal.Zero for i := 1; i <= 10; i++ { sum = sum.Add(decimal.NewFromInt(int64(i))) } fmt.Println(sum) // 输出:55
JSON 序列化和反序列化:
type Item struct { Price decimal.Decimal `json:"price"` } item := Item{Price: decimal.NewFromFloat(19.99)} jsonData, _ := json.Marshal(item) fmt.Println(string(jsonData)) // 输出:{"price":"19.99"} var newItem Item json.Unmarshal(jsonData, &newItem) fmt.Println(newItem.Price) // 输出:19.99
科学计数法支持:
d, _ := decimal.NewFromString("1.23e4") fmt.Println(d) // 输出:12300
注意事项
decimal
库避免了浮点数精度问题,但需要注意性能开销。- 对于需要频繁处理高精度计算的场景,可以通过复用
Decimal
实例来提高效率。 - 确保正确处理错误,例如
NewFromString
返回的错误。