Golang中浮点数算术平均值的计算方法

Golang中浮点数算术平均值的计算方法 一个愚蠢的问题,但下面的代码片段有一个我找不到的错误

var (
        an float64
    	n, avg = 0, 0.
   )

for ; ; n++ {
	fmt.Print("number? ")
	fmt.Scan(&an)
	if an == 0. {
		break
	}
	avg += an
}

if n != 0 {
	fmt.Println(avg / float64(n))
}

程序输出是

number? 5.1
number? 2.1
number? 0
3.5999999999999996

而不是3.6,为什么?


更多关于Golang中浮点数算术平均值的计算方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

8 回复

更多关于Golang中浮点数算术平均值的计算方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这只会导致更多问题。如果你需要精度,那么请使用具有精度的类型。

如果只是用于显示目的,那么在调用 fmt.Printf 时使用适当的注解。

fmt.Printf

好的,我通过谷歌找到了以下代码片段 https://play.golang.org/p/KNhgeuU5sT 它解决了这个问题 谢谢。

好的,你有什么建议可以让我对结果进行四舍五入吗?也许可以使用系统误差常数 .0000000000000005?

你无法将任何值向上或向下舍入到一个无法表示的值。

我们提供的所有链接都讲述了浮点数计算固有的不精确性,无论你所在的领域是否可以安全地允许这种不精确性(例如计算机图形学),或者不能(例如货币处理)。

好的,在这种情况下,我可以使用 fmt.Printf 来对结果进行四舍五入,或者使用 math.big 来处理精度为 3.5999999999999996 的输入数据,对吗?

由于浮点数存在已知的不精确性问题。

如果需要精确值,就需要使用精确的类型。

关于这个话题有很多博客文章,我选取了谷歌搜索"浮点数货币"的前三个结果(因为货币是最常用的"精确值"示例):

(* 我最近没有读过这些文章,它们只是谷歌搜索的前几个结果)

这是一个典型的浮点数精度问题,不是代码逻辑错误。在Go语言中,浮点数使用IEEE 754标准表示,某些十进制小数无法精确表示为二进制浮点数,导致精度损失。

你的代码计算 (5.1 + 2.1) / 2 时,5.1和2.1在二进制表示中都是近似值,累加和除法后产生了微小的误差。

以下是验证和解决方案:

package main

import (
	"fmt"
	"math"
)

func main() {
	// 验证浮点数精度问题
	fmt.Printf("5.1 的精确值: %.20f\n", 5.1)
	fmt.Printf("2.1 的精确值: %.20f\n", 2.1)
	fmt.Printf("和的值: %.20f\n", 5.1+2.1)
	fmt.Printf("平均值: %.20f\n", (5.1+2.1)/2)
	
	// 解决方案1:格式化输出
	var (
		an       float64
		n, avg   = 0, 0.
	)
	
	for ; ; n++ {
		fmt.Print("number? ")
		fmt.Scan(&an)
		if an == 0. {
			break
		}
		avg += an
	}
	
	if n != 0 {
		// 使用格式化输出控制精度
		fmt.Printf("平均值: %.2f\n", avg/float64(n))
	}
	
	// 解决方案2:使用math.Round进行四舍五入
	if n != 0 {
		result := avg / float64(n)
		rounded := math.Round(result*100) / 100 // 保留两位小数
		fmt.Printf("四舍五入后的平均值: %.2f\n", rounded)
	}
}

输出示例:

number? 5.1
number? 2.1
number? 0
平均值: 3.60
四舍五入后的平均值: 3.60

关键点:

  • 浮点数运算存在固有的精度限制
  • 使用 fmt.Printf 格式化输出控制显示精度
  • 需要精确计算时使用 math.Round 等函数进行舍入处理
  • 对于金融等需要精确计算的场景,建议使用 math/big
回到顶部