Go 浮点型与复数类型详解📘
Go 浮点型与复数类型详解
一、核心重点(快速掌握)
序号 | 重点内容 | 备注说明 |
---|---|---|
1 | 浮点类型:float32 和 float64 |
分别表示单精度和双精度浮点数,对应 IEEE-754 标准 |
2 | 默认浮点字面量为 float64 |
若不显式指定类型,默认是 float64 |
3 | 支持科学计数法 | 如 1.23e4 表示 12300 |
4 | 浮点运算可能产生误差 | 不适用于高精度金融计算,建议使用 decimal 等库 |
5 | 复数类型:complex64 和 complex128 |
基于 float32 和 float64 构成的复数 |
6 | 使用内置函数操作复数 | 如 real() 、imag() 获取实部和虚部 |
7 | NaN 和 Inf 的判断方式 | 使用 math.IsNaN() 、math.IsInf() 判断特殊值 |
8 | 避免直接比较浮点数相等 | 推荐使用差值小于某个极小值(如 1e-9 )来判断近似相等 |
二、知识点详解(专题深入)
1、浮点类型(Floating Point Types)
Go 提供了两种浮点类型:
类型名 | 所占字节数 | 精度位数 | IEEE-754标准 |
---|---|---|---|
float32 | 4 | 约7位 | 单精度 |
float64 | 8 | 约15位 | 双精度 |
注意点:
float64
是默认类型,大多数情况下推荐使用。- 对性能要求极高或内存受限时可考虑使用
float32
。
实例代码:
package main
import "fmt"
func main() {
var a float32 = 3.1415926535
var b float64 = 3.1415926535
fmt.Printf("a = %.10f (float32)\n", a) // 输出精度损失
fmt.Printf("b = %.10f (float64)\n", b) // 输出更精确
}
2、浮点数字面量表示法
Go 支持以下几种浮点数字面量格式:
表达方式 | 示例 | 描述 |
---|---|---|
小数形式 | 3.14 , -0.001 |
包含整数部分和小数部分 |
科学记数法 | 1.23e4 , 3E-5 |
e 或 E 表示指数 |
显式类型声明 | float32(1.2) |
强制转换为特定浮点类型 |
实例代码:
package main
import "fmt"
func main() {
a := 1.23
b := 1.23e4
c := float32(1.23)
fmt.Printf("a: %T\n", a) // float64
fmt.Printf("b: %v\n", b) // 12300
fmt.Printf("c: %T\n", c) // float32
}
技巧:
- 使用科学记数法可以简化极大或极小数值的书写。
- 可以通过类型断言或转换控制变量类型。
3、浮点数的精度问题与陷阱
由于浮点数采用二进制表示,某些十进制小数无法精确表示,导致精度丢失。
实例代码:
package main
import "fmt"
func main() {
a := 0.1 + 0.2
fmt.Println(a == 0.3) // 输出 false!
}
注意点:
- 不要直接用
==
比较两个浮点数是否相等。 - 推荐使用差值比较,例如:
const epsilon = 1e-9
if math.Abs(a - b) < epsilon {
fmt.Println("a ≈ b")
}
技巧:
- 高精度场景建议使用
big.Float
或第三方库如shopspring/decimal
。
4、复数类型(Complex Numbers)
Go 支持两种复数类型:
类型名 | 内部结构 | 总字节数 |
---|---|---|
complex64 | float32 + float32 | 8 |
complex128 | float64 + float64 | 16 |
注意点:
- 默认复数字面量是
complex128
。 - 使用
i
表示虚数单位。
实例代码:
package main
import "fmt"
func main() {
var c1 complex64 = 3 + 4i
var c2 complex128 = complex(5, 12) // 5+12i
fmt.Println("c1 =", c1)
fmt.Println("c2 =", c2)
}
5、复数的基本操作函数
Go 提供了一些内置函数用于操作复数:
函数名 | 功能描述 |
---|---|
real(c) |
返回复数 c 的实部 |
imag(c) |
返回复数 c 的虚部 |
complex(r, i) |
构造一个复数 |
实例代码:
package main
import "fmt"
func main() {
c := complex(3, 4) // 创建复数 3+4i
r := real(c) // 实部 3
i := imag(c) // 虚部 4
fmt.Printf("Real part: %v\n", r)
fmt.Printf("Imaginary part: %v\n", i)
}
技巧:
- 使用
cmath
包进行复数数学运算(如平方根、指数、对数等)。
6、浮点数的特殊值处理(NaN、Inf)
Go 中使用 math
包定义了一些特殊浮点值和检测函数:
常量 / 函数 | 含义 |
---|---|
math.NaN() |
表示“非数字”(Not-a-Number) |
math.Inf(1) |
表示正无穷 |
math.IsNaN(x) |
判断是否为 NaN |
math.IsInf(x, 0) |
判断是否为无穷 |
实例代码:
package main
import (
"fmt"
"math"
)
func main() {
a := math.NaN()
b := math.Inf(1)
fmt.Println("IsNaN(a):", math.IsNaN(a)) // true
fmt.Println("IsInf(b):", math.IsInf(b, 0)) // true
}
注意点:
- NaN 与任何值(包括自己)都不相等,必须使用
math.IsNaN()
判断。 - 在除法、开方等操作中可能出现这些特殊值。
7、常见陷阱与注意事项汇总
陷阱/问题 | 解决方案/建议 |
---|---|
浮点数精度丢失 | 避免直接比较,使用差值比较;高精度需求使用专用库 |
错误地使用 float32 导致精度不足 |
优先使用 float64 |
直接使用 == 比较浮点数 |
使用 math.Abs(a - b) < epsilon |
忽略复数的构造方式 | 使用 complex(r, i) 更清晰可靠 |
复数未导入 math/cmplx 包进行复杂运算 |
若需三角函数、幂运算等,需引入 cmath 包 |
忽略 NaN 和 Inf 的存在 | 在除法、开方等操作后应做边界检查 |
✅ 总结
本章详细讲解了 Go 语言中的浮点类型和复数类型的定义、使用方法、常见陷阱及最佳实践。涵盖了如下内容:
float32
与float64
的区别与选择- 浮点数字面量的多种写法(包括科学记数法)
- 浮点数的精度问题与比较技巧
- 复数类型的定义与基本操作(实部、虚部、构造)
- 特殊值(NaN、Inf)的使用与检测
- 常见错误与规避策略
建议结合练习项目进一步巩固理解,如实现一个简单的计算器、向量运算器或信号处理模块,提升实际应用能力。若需继续学习字符串、布尔、数组等基础类型,请继续提问。