float32和float64
float32 和 float64
Go语⾔中提供了两种精度的浮点数 float32 和 float64。
float32,也即我们常说的单精度,存储占⽤4个字节,也即4*8=32位,其中1位⽤来符号,8位⽤来指数,剩下的23位表⽰尾数
float64,也即我们熟悉的双精度,存储占⽤8个字节,也即8*8=64位,其中1位⽤来符号,11位⽤来指数,剩下的52位表⽰尾数
那么精度是什么意思?有效位有多少位?
精度主要取决于尾数部分的位数。
float数值范围对于 float32(单精度)来说,表⽰尾数的为23位,除去全部为0的情况以外,最⼩为2-23,约等于1.19*10-7,所以float⼩数部分只能精确到后⾯6位,加上⼩数点前的⼀位,即有效数字为7位。
同理 float64(单精度)的尾数部分为 52位,最⼩为2-52,约为2.22*10-16,所以精确到⼩数点后15位,加上⼩数点前的⼀位,有效位数为16位。
通过以上,可以总结出以下⼏点:
⼀、float32 和 float64 可以表⽰的数值很多
浮点数类型的取值范围可以从很微⼩到很巨⼤。浮点数取值范围的极限值可以在 math 包中到:
常量 math.MaxFloat32 表⽰ float32 能取到的最⼤数值,⼤约是 3.4e38;
常量 math.MaxFloat64 表⽰ float64 能取到的最⼤数值,⼤约是 1.8e308;
float32 和 float64 能表⽰的最⼩值分别为 1.4e-45 和 4.9e-324。
⼆、数值很⼤但精度有限
⼈家虽然能表⽰的数值很⼤,但精度位却没有那么⼤。
float32的精度只能提供⼤约6个⼗进制数(表⽰后科学计数法后,⼩数点后6位)的精度
float64的精度能提供⼤约15个⼗进制数(表⽰后科学计数法后,⼩数点后15位)的精度
这⾥的精度是什么意思呢?
⽐如 10000018这个数,⽤ float32 的类型来表⽰的话,由于其有效位是7位,将10000018 表⽰成科学计数法,就是 1.0000018 * 10^7,能精确到⼩数点后⾯6位。
此时⽤科学计数法表⽰后,⼩数点后有7位,刚刚满⾜我们的精度要求,意思是什么呢?此时你对这个数进⾏+1或者-1等数学运算,都能保证计算结果是精确的
import "fmt"
var myfloat float32 = 10000018
func main() {
fmt.Println("myfloat: ", myfloat)
fmt.Println("myfloat: ", myfloat+1)
}
/*
myfloat: 1.0000018e+07
myfloat: 1.0000019e+07
/
上⾯举了⼀个刚好满⾜精度要求数据的临界情况,为了做对⽐,下⾯也举⼀个刚好不满⾜精度要求的例⼦。只要给这个数值多加⼀位数就⾏了。
换成 100000187,同样使⽤ float32类型,表⽰成科学计数法,由于精度有限,表⽰的时候⼩数点后⾯7位是准确的,但若是对其进⾏数学运算,由于第⼋位⽆法表⽰,所以运算后第七位的值,就会变得不精确。
这⾥我们写个代码来验证⼀下,按照我们的理解下⾯ myfloat01 = 100000182 ,对其+5 操作后,应该等于 myfloat02 = 100000187,
import "fmt"
var myfloat01 float32 = 100000182
var myfloat02 float32 = 100000187
func main() {
fmt.Println("myfloat: ", myfloat01)
fmt.Println("myfloat: ", myfloat01+5)
fmt.Println(myfloat02 == myfloat01+5)
}
但是由于其类型是 float32,精度不⾜,导致最后⽐较的结果是不相等(从⼩数点后第七位开始不精确)myfloat: 1.00000184e+08
myfloat: 1.0000019e+08
false
由于精度的问题,就会出现这种很怪异的现象,myfloat == myfloat +1 会返回 true 。