duke-git / lancet

A comprehensive, efficient, and reusable util function library of Go.

Home Page:https://www.golancet.cn/en/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

四舍五入保留两位小数金额不对,64.585结果应该是64.59,但输出结果是64.58

chengfny opened this issue · comments

四舍五入保留两位小数金额不对,64.585结果应该是64.59,但结果是64.58。而63.585的结果是正确的63.59
WechatIMG16407

@chengfny

浮点数运算基于 IEEE754 标准,丢精度可能是无法避免的

我看别人的代码有种精度更高的实现方式:

func Round(val float64, precision int) float64 {
	if precision == 0 {
		return math.Round(val)
	}
	p := math.Pow10(precision)
	if precision < 0 {
		return math.Floor(val*p+0.5) * math.Pow10(-precision)
	}
	return math.Floor(val*p+0.5) / p
}

但是仍然无法避免这个问题,如果需要准确的运算,你或许可以试试 github.com/shopspring/decimal

示例

可以使用decimal包解决

func RoundToString[T constraints.Float | constraints.Integer](x T, n int) string {
	d, _ := decimal.NewFromString(convertor.ToString(x))
	f, _ := d.Round(int32(n)).Float64()
	return strconv.FormatFloat(f, 'f', n, 64)
}

@chengfny

浮点数运算基于 IEEE754 标准,丢精度可能是无法避免的

我看别人的代码有种精度更高的实现方式:

func Round(val float64, precision int) float64 {
	if precision == 0 {
		return math.Round(val)
	}
	p := math.Pow10(precision)
	if precision < 0 {
		return math.Floor(val*p+0.5) * math.Pow10(-precision)
	}
	return math.Floor(val*p+0.5) / p
}

但是仍然无法避免这个问题,如果需要准确的运算,你或许可以试试 github.com/shopspring/decimal

示例

https://github.com/duke-git/lancet/blob/main/README_zh-CN.md?plain=1#L27
项目介绍里提到 只依赖 go 标准库和 golang.org/x

可以使用decimal包解决

func RoundToString[T constraints.Float | constraints.Integer](x T, n int) string {
	d, _ := decimal.NewFromString(convertor.ToString(x))
	f, _ := d.Round(int32(n)).Float64()
	return strconv.FormatFloat(f, 'f', n, 64)
}

@chengfny

浮点数运算基于 IEEE754 标准,丢精度可能是无法避免的
我看别人的代码有种精度更高的实现方式:

func Round(val float64, precision int) float64 {
	if precision == 0 {
		return math.Round(val)
	}
	p := math.Pow10(precision)
	if precision < 0 {
		return math.Floor(val*p+0.5) * math.Pow10(-precision)
	}
	return math.Floor(val*p+0.5) / p
}

但是仍然无法避免这个问题,如果需要准确的运算,你或许可以试试 github.com/shopspring/decimal
示例

https://github.com/duke-git/lancet/blob/main/README_zh-CN.md?plain=1#L27 项目介绍里提到 只依赖 go 标准库和 golang.org/x

可以使用decimal包解决

func RoundToString[T constraints.Float | constraints.Integer](x T, n int) string {
	d, _ := decimal.NewFromString(convertor.ToString(x))
	f, _ := d.Round(int32(n)).Float64()
	return strconv.FormatFloat(f, 'f', n, 64)
}

@chengfny

浮点数运算基于 IEEE754 标准,丢精度可能是无法避免的
我看别人的代码有种精度更高的实现方式:

func Round(val float64, precision int) float64 {
	if precision == 0 {
		return math.Round(val)
	}
	p := math.Pow10(precision)
	if precision < 0 {
		return math.Floor(val*p+0.5) * math.Pow10(-precision)
	}
	return math.Floor(val*p+0.5) / p
}

但是仍然无法避免这个问题,如果需要准确的运算,你或许可以试试 github.com/shopspring/decimal
示例

那就只能他自己用decimal包解决了