问题
在处理金额等数字时,需要处理小数。如果在前端页面使用float类型传递的话,会丢失精度,会造成影响。
而且通常MySQL之类的db也没有很好的方法处理小数。
需求1
- 需要找一个方法处理小数问题,并且尽量不丢失精度
方案
设计API的时候,前端直接传递用户输入的数字,类型为string,比如“1.23456789”。
后端直接处理这个字符串,保存到db的时候,可以考虑:
- 直接保存字符串
- 优点:简单,容易理解
- 缺点:不利于使用数据库搜索
- 转换成一定倍率的int64,然后保存,例如:需求是保留5位小数,那么转换成123456,然后保存
- 优点:可以使用数据库搜索
- 缺点:输入输出需要转换,而且每次操作都不能忘记转换,比较繁琐
需求2
- 处理超过int64的加减乘除
方案
输入输出都是字符串,实现加减乘除,然后做除法时能自定义精度
golang 例子
package main
import (
"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:12345678
Int64ToFloatString, int64WithPricision:12345678, floatString:123.45678
Add -0.00034567 -12.345678 -12.34602367
Sub -0.00034567 -12.345678 12.34533233
Mul -0.00034567 -12.345678 0.00426753051426
Quo -0.00034567 -12.345678 0.0000279992