【原】Go浮点型计算

/ 0评 / 0

最近在看《Go语言趣学指南》,刚看完浮点数,这里做一些自己的理解和总结,顺便做一下最后的实验。

一、浮点型类型说明

Go语言有两种浮点型类型,其中默认的浮点类型是float64,每个64位的浮点型数据需要占用8字节的内存。很多语言也称这种数据类型为双精度浮点数。

Go语言的另一种浮点类型是float32,又称单精度浮点数,占用内存是float64的一半,但是float32提供的精度不如float64高。

下面举例使用两种浮点型数据

dfunc main() {
    var pi64 = math.Pi
    var pi32 float32 = math.Pi
    
    fmt.Println(pi64)
    fmt.Println(pi32)
}

打印结果如下:

3.141592653589793
3.1415927

提示:math包里的函数处理的都是float64类型的值,所以除非有特殊理由,否则应该优先使用float64的类型。

二、浮点型数据计算

这里为什么要说浮点型数据计算呢?是因为浮点精确性的问题,请看下面举例

func main() {
    third := 1.0 / 3
    fmt.Println(third + third + third)
    
    variate := 0.1
    variate += 0.2
    fmt.Println(variate)
}

1
0.30000000000000004

我用LeetCode的测试了一下,截图如下

正如以上实验所见,浮点数也许会出现计算精度的问题,因此也许并不是表示金钱余额交易的醉驾选择。我们可以采用“放大法”来解决此类问题。例如金额通常是2位小数,将金额放大100倍后,就会变成整数,然后用整数运算便会准确。

三、浮点数比较

在上面的例子中,我们将变量variate的初始值0.1累加0.2以后,原本想要0.3,但是因为精度问题变成了0.30000000000000004。这时候我们比较的时候就要小心了。

func main() { 
    variate := 0.1
    variate += 0.2
    fmt.Println(variate == 0.3) //输出false
}

为避免以上问题,可以采用计算两个浮点数的差值,然后用绝对值是否足够小来判断。

四、总结

虽然没有详细介绍Go的浮点数,但是这里做一个总结,说一下浮点数的一些特点。

五、实验

本实验是《Go语言趣学指南》第六章实数的最后一个实验。原题目是:请编写一个程序用于模拟存钱为朋友购买礼物的情景,这个程序会随机地往存钱罐里存入5美分(0.05美元)、10美分(0.1美元)和25美分(0.25美元)的硬币,直到存款超过20.00美元为止,并且每次存款后按照适当的精度和宽度打印出格式化之后的当前余额。

func main() {
	moneys := []float64{0.05,0.1,0.25}
	deposit := 0.0
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for  {
		money := moneys[r.Intn(2)]
		deposit += money
		if deposit < 10.0{
			fmt.Printf("%04.2f\n",deposit)
		}else if deposit >= 20.0{
			fmt.Printf("%05.2f\n",deposit)
			return
		}else {
			fmt.Printf("%05.2f\n",deposit)
		}
	}
}

实验如有不对之处,还请留言评论。