问题
在处理金额等数字时,需要处理小数。如果在前端页面使用float类型传递的话,会丢失精度,会造成影响。
而且通常MySQL之类的db也没有很好的方法处理小数。
需求1
- 需要找一个方法处理小数问题,并且尽量不丢失精度
方案
设计API的时候,前端直接传递用户输入的数字,类型为string,比如“1.23456789”。
后端直接处理这个字符串,保存到db的时候,可以考虑:
- 直接保存字符串
- 优点:简单,容易理解
- 缺点:不利于使用数据库搜索
- 转换成一定倍率的int64,然后保存,例如:需求是保留5位小数,那么转换成123456,然后保存
- 优点:可以使用数据库搜索
- 缺点:输入输出需要转换,而且每次操作都不能忘记转换,比较繁琐
需求2
- 处理超过int64的加减乘除
方案
输入输出都是字符串,实现加减乘除,然后做除法时能自定义精度
golang 例子
package mainimport ("fmt""github.com/lvshuchengyin/gobignumber")const (DecimalPlaces = 5)func main() {floatString := "123.456789"int64WithPricision := int64(0)int64WithPricision, err := gobignumber.FloatStringToInt64(floatString, DecimalPlaces)if err != nil {fmt.Println("FloatStringToInt64 err", err.Error())return}fmt.Printf("FloatStringToInt64, floatString:%v, int64WithPricision:%v\n", floatString, int64WithPricision)floatString, err = gobignumber.Int64ToFloatString(int64WithPricision, DecimalPlaces)if err != nil {fmt.Println("Int64ToFloatString err", err.Error())return}fmt.Printf("Int64ToFloatString, int64WithPricision:%v, floatString:%v\n", int64WithPricision, floatString){sbn, _ := gobignumber.NewBigNumberFromString("-0.00034567")sbn2, _ := gobignumber.NewBigNumberFromString("-12.345678")sbn3 := sbn.Add(sbn2)fmt.Println("Add", sbn, sbn2, sbn3)}{sbn, _ := gobignumber.NewBigNumberFromString("-0.00034567")sbn2, _ := gobignumber.NewBigNumberFromString("-12.345678")sbn3 := sbn.Sub(sbn2)fmt.Println("Sub", sbn, sbn2, sbn3)}{sbn, _ := gobignumber.NewBigNumberFromString("-0.00034567")sbn2, _ := gobignumber.NewBigNumberFromString("-12.345678")sbn3 := sbn.Mul(sbn2)fmt.Println("Mul", sbn, sbn2, sbn3)}{sbn, _ := gobignumber.NewBigNumberFromString("-0.00034567")sbn2, _ := gobignumber.NewBigNumberFromString("-12.345678")sbn3 := sbn.Quo(sbn2, 10)fmt.Println("Quo", sbn, sbn2, sbn3)}}
输出
FloatStringToInt64, floatString:123.456789, int64WithPricision:12345678Int64ToFloatString, int64WithPricision:12345678, floatString:123.45678Add -0.00034567 -12.345678 -12.34602367Sub -0.00034567 -12.345678 12.34533233Mul -0.00034567 -12.345678 0.00426753051426Quo -0.00034567 -12.345678 0.0000279992