Golang 小数计算现状:
存在精度损失
d := 1129.6
fmt.Println((d * 100)) //输出:112959.99999999999
var d float64 = 1129.6
fmt.Println((d * 100)) //输出:112959.99999999999
m1 := 8.2
m2 := 3.8
fmt.Println(m1 - m2) // 期望是4.4,结果打印出了4.399999999999999
解决方案:
Decimal
由于golang中默认没有decimal类型,如果想使用decimal类型需要通过第三方包
go get github.com/shopspring/decimal
decimal使用方式
package main
import (
"fmt"
"github.com/shopspring/decimal"
)
func main() {
var v1 = decimal.NewFromFloat(0.1)
var v2 = decimal.NewFromFloat(0.2)
var v3 = v1.Add(v2) // 0.3
var v4 = v1.Sub(v2) // -0.1
var v5 = v1.Mul(v2) // 0.02
var v6 = v1.Div(v2) // 0.5
var v7 = decimal.NewFromFloat(3.4625)
var data1 = v7.Round(1) // 3.5 保留一位小数,四舍五入
var data2 = v7.Truncate(1) // 3.4 保留一位小数,直接舍弃
fmt.Println(v3, v4, v5, v6)
fmt.Println(data1, data2)
}
注意:
运算过程中数据全部变为 decimal.Decimal 格式,在最后计算时需要将其转换成需要的格式
package main
import (
"fmt"
"github.com/shopspring/decimal"
)
func main() {
var v1 = decimal.NewFromFloat(0.1)
var v1 = decimal.NewFromFloat(0.1)
var resp1 float64
var resp2 string
resp1, _ = v1.Float64() // note: 注意这边第二个参数并不是ok,而是是否准确
resp2 = v1.String()
fmt.Printf("resp1 = %v, type = %v\n", resp1, reflect.TypeOf(resp1).String())
// output: resp1 = 0.1, type = float64
fmt.Printf("resp2 = %v, type = %v\n", resp2, reflect.TypeOf(resp2).String())
// output: resp2 = 0.1, type = string
}