Golang 浮点数运算 避免精度损失 Decimal包

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
}

你可能感兴趣的:(Go,golang,开发语言,后端)