Go语言中的浮点数类型详解

Go语言提供了两种浮点数类型:float32和float64,分别对应IEEE-754标准的单精度和双精度浮点数。

1. 浮点数类型概述

1.1. float32 (单精度浮点数)

  1. 占用32位即4字节的存储空间;

  2. 大约提供6-7位十进制精度;

  3. 范围约为 ±1.18e-38 到 ±3.4e38;

1.2. float64 (双精度浮点数)

  1. 占用64位即8字节存储空间;

  2. 大约提供15-16位十进制精度;

  3. 范围约为 ±2.23e-308 到 ±1.8e308;

2. 浮点数声明与初始化

javascript 复制代码
var f1 float32 = 3.14
var f2 float64 = 3.141592653589793

// 简写形式(默认为float64)
f3 := 3.14  // float64

3. 浮点数精度问题

由于浮点数的二进制表示特性,某些十进制小数无法精确表示:

javascript 复制代码
func main() {
    f := 0.1
    sum := f + f + f
    fmt.Println(sum) // 输出: 0.30000000000000004
}

如果要解决浮点数运算的精度问题,可以使用第三方的包 decimal 。

javascript 复制代码
package main
import (
    "fmt" 
    "github.com/shopspring/decimal"
)
func main() {

    // 加法
    var num1 float64 = 3.1
    var num2 float64 = 4.2
    num3 := decimal.NewFromFloat(num1).Add(decimal.NewFromFloat(num2))
    fmt.Println(num3)

    // 减去
    m1 := 8.2
    m2 := 3.8
    m3 := decimal.NewFromFloat(m1).Sub(decimal.NewFromFloat(m2))
    fmt.Println(m3)
}

4. 特殊浮点数值

Go浮点数支持IEEE-754定义的特殊值:

  1. 正无穷大(+Inf)和负无穷大(-Inf)

  2. 非数(NaN, Not a Number)

javascript 复制代码
func main() {
    posInf := math.Inf(1)   // 正无穷
    negInf := math.Inf(-1)  // 负无穷
    nan := math.NaN()       // 非数
    
    fmt.Println(posInf, negInf, nan)
}

5. 浮点数比较

由于精度问题,直接比较浮点数可能不可靠:

javascript 复制代码
// 不推荐的比较方式
if a == b { ... }

// 推荐的比较方式(使用允许的误差范围)
const epsilon = 1e-9
if math.Abs(a-b) < epsilon { ... }

对于NaN的比较:

javascript 复制代码
if math.IsNaN(x) { ... }

6. 数学运算

Go的math包提供了丰富的浮点数运算函数:

javascript 复制代码
func main() {
    a := 2.0
    b := 3.0
    
    fmt.Println(math.Sqrt(a))      // 平方根
    fmt.Println(math.Pow(a, b))    // 幂运算
    fmt.Println(math.Sin(a))       // 正弦
    fmt.Println(math.Log(a))       // 自然对数
    fmt.Println(math.Floor(a))     // 向下取整
    fmt.Println(math.Ceil(a))      // 向上取整
    fmt.Println(math.Mod(a, b))    // 取模
}

7. 类型转换

javascript 复制代码
func main() {
    var f32 float32 = 1.5
    var f64 float64 = 2.7
    
    // float32转float64
    f64 = float64(f32)
    
    // float64转float32(可能丢失精度)
    f32 = float32(f64)
    
    // 整数转浮点数
    i := 10
    f32 = float32(i)
    f64 = float64(i)
}

8. 格式化输出

javascript 复制代码
func main() {
    f := 123.456
    
    fmt.Printf("%f\n", f)    // 默认格式: 123.456000
    fmt.Printf("%.2f\n", f)  // 保留两位小数: 123.46
    fmt.Printf("%e\n", f)    // 科学计数法: 1.234560e+02
    fmt.Printf("%g\n", f)    // 根据情况选择%f或%e: 123.456
}

9. 最佳实践

  1. 在大多数情况下,优先使用float64以获得更高的精度;

  2. 避免直接比较浮点数,应使用允许的误差范围;

  3. 注意浮点数的精度限制,特别是涉及金钱计算时;

  4. 对于需要精确十进制计算的场景,考虑使用math/big包;

10. 性能考虑

  1. float32占用更少内存,适合大量数据存储;

  2. float64提供更高精度,是Go中默认的浮点类型;

  3. 在现代CPU上,float32和float64的运算性能差异通常不大;

通过理解Go语言中浮点数的这些特性和行为,可以避免常见的精度问题,并编写出更可靠的数值计算代码。

相关推荐
唐青枫9 小时前
别再把 struct 只当字段集合:Go 结构体从语法到项目实战
go
程序员老邢16 小时前
《技术底稿 46》AI 解构成果→知识库自动化同步管道 设计与落地总结
架构设计·异步任务·数据同步·后端开发·幂等性·技术底稿
踏着七彩祥云的小丑20 小时前
Go学习第4天:条件、循环语句+函数
学习·golang·go
tyung2 天前
Go 手写 Wait-Free SPSC 无界队列:无 CAS、无锁、泛型节点池
数据结构·后端·go
踏着七彩祥云的小丑2 天前
Go学习第3天:变量+常量+运算符
开发语言·学习·golang·go
踏着七彩祥云的小丑3 天前
Go学习第2天:程序结构+基础语法+数据类型
开发语言·学习·golang·go
吴佳浩4 天前
AI Infra 的真相:Go 没输,rust也不是取代
后端·rust·go
2601_959644894 天前
2026年权威AI引擎优化服务咨询,专业之选
go
逐光老顽童4 天前
用 Go 实现一个 LLM 路由网关:Thompson Sampling 与自适应故障转移实践
vue.js·go
蓝宝石的傻话4 天前
MiBeeNvr v0.6.0: 延时摄影 + 转码界面 + ONVIF 增强 + 文档重构
go·github