Go语言提供了两种精度的浮点数,单精度float32和双精度float64。它们的算术规范由IEEE754浮点数国际标准定义,该浮点数规范被所有现代的CPU支持。
类型 |
范围 |
float32 |
最小近似值1.4e-45,具体可以用通过math.SmallestNonzeroFloat32查看 最大近似值大约是3.4e38,具体可以通过math.MaxFloat32查看 |
float64 |
最小近似值4.9e-324,具体可以用通过math.SmallestNonzeroFloat64查看 最大近似值大约是1.8e308,具体可以通过math.MaxFloat64查看 |
声明语法如下
| var 变量名 浮点型类型 = 初始化表达式/字面量 |
格式化输出
| var f float64 = 3.931 |
| fmt.Printf("%8.3f\n", f) |
注意点:
- 1、宽度也是类型的一部分,float32与float64是两种不同的类型
| var x float32 = 10.1 |
| var y float64 |
| y = x |
| f := 3.931 |
| fmt.Printf("%T\n",f) |
- 3、如果不加小数点,默认会被推导为整型而不是浮点型
| f := 3 |
| fmt.Printf("%T\n",f) |
| |
| f1 := 3.0 |
| fmt.Printf("%T\n",f1) |
- 4、通常应该优先使用float64,因float64的精度以及表示的正整数范围都要比float32大
| var x float32 =3.6666666666666666666666666666666666666666 |
| fmt.Println(x) |
| var y float64 =3.6666666666666666666666666666666666666666 |
| fmt.Println(y) |
| |
| |
- 5、针对字面值运算10+10.3会被隐式转换为float64,结果也为float64,关于数据类型转换详见下一小节
| fmt.Printf("%T\n", 10+10.3) |
| fmt.Printf("%T\n", 10+float32(10.3)) |
整型与浮点型为兼容类型,可以相互转换,本节我们主要介绍:整型、浮点型转为—>浮点型,其实与上一小节介绍的转换套路都是一样的,如下
一:显式转换规则如下:
-
1.1、无类型的量(无类型的整数、无类型的浮点数)可以转为浮点型,超出目标类型值域范围就报错
| fmt.Println(math.MaxFloat32) |
| fmt.Println(math.SmallestNonzeroFloat32) |
| |
| |
| fmt.Println(float32(1000000000000000000000000000000000000000)) |
| |
| |
| fmt.Println(float32(340282346638528860000000000000000000000)) |
| fmt.Println(float32(340282346638528865555555555555555555555)) |
| fmt.Println(float32(340282346638528869999999999999999999999)) |
-
1.2、有类型的量(有类型的整数、有类型的浮点数)也可以转为浮点型,超出目标类型值域范围不报错,但是浮点数会溢出,应该尽量避免
| fmt.Println(math.MaxFloat64) |
| var x float64 = 1.7976931348623157e+308 |
| |
| fmt.Println(float32(x)) |
强调:我们应该尽量避免溢出!!大多数情况情况下,只是为了统一类型,而不要改变原值
| var apples int32 = 1 |
| var oranges int16 = 2 |
| var compote = float32(apples) + float32(oranges) |
| fmt.Printf("%T,%v\n",compote,compote) |
二:隐式转换,只针对无类型的量
| var x float64 = 10.3 |
| fmt.Printf("%T\n",x + 10.66) |
浮点型也属于数字,重申一遍:数字之间支持加减乘除等算数运算以及比较运算,但仅限于同类型之间,非同类型经隐式或显式转换成相同类型后也可以。示例如下
(1)算数运算
| |
| var x float64 = 10 |
| var y float32 = 20 |
| fmt.Println(x + y) |
| fmt.Println(x + float64(y)) |
| |
| |
| var x float64 = 10 |
| fmt.Println(x + 10.3) |
| fmt.Println(x + 10.0) |
| |
| |
| var x int32 = 1 |
| var y int64 = 2 |
| var z = float64(x) + float64(y) |
| fmt.Println(z) |
(2)相等性比较
| |
| var x float64 = 10.3 |
| var y float64 = 10.3 |
| fmt.Println(x == y) |
| fmt.Println(x != y) |
| |
| |
| |
| |
| |
| |
| |
| |
| var m float64 = 10.3 |
| fmt.Println(m == 10.3) |
| fmt.Println(m == 10) |
(3)比大小
| var x float32 = 10 |
| var y float64 = 3 |
| |
| |
| |
| fmt.Println(x > float32(y)) |
| |
| |
| fmt.Println(x > 3) |
| fmt.Println(x > 3.1) |
| |
| |
| fmt.Println(10 > 3.1) |
因为浮点数不是一种精确的表达方式,所以像整型那样直接用==来判断两个浮点数是否相等是不可行的,这可能会导致不稳定的结果,例如
| package main |
| |
| import ( |
| "fmt" |
| ) |
| func main() { |
| x := 0.1 |
| y := 0.2 |
| |
| res := x + y |
| fmt.Println(res) |
| fmt.Println(res == 0.3) |
| |
| } |
浮点数的精度问题与解决方案详见《附录:浮点数的精度问题》,精度问题解决方案见你文章末尾。
另外,无类型的常量有更高的计算精度
| package main |
| |
| import "fmt" |
| |
| func main() { |
| |
| const x = 0.1 |
| const y = 0.2 |
| |
| res := x + y |
| fmt.Println(res) |
| fmt.Println(res == 0.3) |
| |
| var m = 0.3 |
| fmt.Println(m == 0.1+0.2) |
了解:浮点数里有个叫非数的东西
| fmt.Println(math.NaN()) |
| |
| var z float32 |
| fmt.Println(z) |
| fmt.Println(z/z) |
| |
| x:=z/z |
| fmt.Println(x < x) |
| fmt.Println(x > x) |
| fmt.Println(x == x) |
| fmt.Println(x != x) |
值传递
| Go语言提供了两种精度的复数类型:complex64和complex128,复数实际上由两个实数(在计算机中用浮点数表示,complex64对应的是float32,complex128对应的是float64)构成,一个表示实部(real),一个表示虚部(imag)。 |
内置的complex函数用于构建复数,内建的real和imag函数分别返回复数的实部和虚部:
| var x complex128 = complex(1, 2) |
| var y complex128 = complex(3, 4) |
| fmt.Println(x*y) |
| fmt.Println(real(x*y)) |
| fmt.Println(imag(x*y)) |
如果一个浮点数面值或一个十进制整数面值后面跟着一个i,例如3.141592i或2i,它将构成一个复数的虚部,复数的实部是0:
在常量算术规则下,一个复数常量可以加到另一个普通数值常量(整数或浮点数、实部或虚部),我们可以用自然的方式书写复数,就像1+2i或与之等价的写法2i+1。上面x和y的声明语句还可以简化:
复数也可以用==和!=进行相等比较。只有两个复数的实部和虚部都相等的时候它们才是相等的(译注:浮点数的相等比较是危险的,需要特别小心处理精度问题)。
math/cmplx包提供了复数处理的许多函数,例如求复数的平方根函数和求幂函数,更多关于复数的函数,请查阅math/cmplx标准库的文档。
| fmt.Println(cmplx.Sqrt(-1)) |