【Go】--数据类型

Go 语言数据类型与精度详解

基本数据类型

1. 整数类型

有符号整数
go 复制代码
var a int8   // 1字节,范围:-128 到 127
var b int16  // 2字节,范围:-32768 到 32767
var c int32  // 4字节,范围:-2147483648 到 2147483647
var d int64  // 8字节,范围:-9223372036854775808 到 9223372036854775807
var e int    // 平台相关,32位系统为int32,64位系统为int64
无符号整数
go 复制代码
var a uint8   // 1字节,范围:0 到 255
var b uint16  // 2字节,范围:0 到 65535
var c uint32  // 4字节,范围:0 到 4294967295
var d uint64  // 8字节,范围:0 到 18446744073709551615
var e uint    // 平台相关
var f byte    // uint8 的别名
var g rune    // int32 的别名,表示Unicode码点

2. 浮点数类型

go 复制代码
var a float32     // 4字节,单精度浮点数
var b float64     // 8字节,双精度浮点数(默认类型)
var c complex64   // 8字节,复数,实部和虚部都是float32
var d complex128  // 16字节,复数,实部和虚部都是float64

3. 布尔类型

go 复制代码
var a bool = true
var b bool = false

4. 字符串类型

go 复制代码
var s string = "Hello, World!"

精度

整数精度

go 复制代码
package main

import (
    "fmt"
    "math"
    "unsafe"
)

func main() {
    // 整数类型的精度和范围
    fmt.Printf("int8 范围: %d 到 %d\n", math.MinInt8, math.MaxInt8)
    fmt.Printf("int16 范围: %d 到 %d\n", math.MinInt16, math.MaxInt16)
    fmt.Printf("int32 范围: %d 到 %d\n", math.MinInt32, math.MaxInt32)
    fmt.Printf("int64 范围: %d 到 %d\n", math.MinInt64, math.MaxInt64)
    
    fmt.Printf("uint8 范围: 0 到 %d\n", math.MaxUint8)
    fmt.Printf("uint16 范围: 0 到 %d\n", math.MaxUint16)
    fmt.Printf("uint32 范围: 0 到 %d\n", math.MaxUint32)
    fmt.Printf("uint64 范围: 0 到 %d\n", uint64(math.MaxUint64))
    
    // 大小验证
    var i int
    fmt.Printf("int 大小: %d 字节\n", unsafe.Sizeof(i))
}

浮点数精度

go 复制代码
package main

import (
    "fmt"
    "math"
)

func floatPrecisionDemo() {
    // float32 精度(约6-7位十进制数)
    var f32 float32 = 123.456789
    fmt.Printf("float32 值: %.10f\n", f32) // 输出: 123.4567871094
    
    // float64 精度(约15-16位十进制数)
    var f64 float64 = 123.4567890123456789
    fmt.Printf("float64 值: %.20f\n", f64) // 输出: 123.4567890123456800
    
    // 精度测试
    fmt.Printf("float32 最大正数: %e\n", math.MaxFloat32)
    fmt.Printf("float64 最大正数: %e\n", math.MaxFloat64)
    fmt.Printf("float32 最小正数: %e\n", math.SmallestNonzeroFloat32)
    fmt.Printf("float64 最小正数: %e\n", math.SmallestNonzeroFloat64)
    
    // 浮点数比较(由于精度问题,不要直接比较)
    a := 0.1
    b := 0.2
    c := 0.3
    
    // 错误的比较方式
    fmt.Printf("直接比较: %v\n", a+b == c) // 可能输出 false
    
    // 正确的比较方式
    fmt.Printf("容差比较: %v\n", math.Abs((a+b)-c) < 1e-9) // 输出 true
}

复数精度

go 复制代码
func complexPrecisionDemo() {
    // complex64 精度
    var c1 complex64 = 1.23456789 + 9.87654321i
    fmt.Printf("complex64: %.10f + %.10fi\n", real(c1), imag(c1))
    
    // complex128 精度
    var c2 complex128 = 1.2345678901234567 + 9.8765432109876543i
    fmt.Printf("complex128: %.20f + %.20fi\n", real(c2), imag(c2))
}

类型转换与精度损失

显式类型转换

go 复制代码
package main

import "fmt"

func typeConversionDemo() {
    // 整数类型转换
    var big int64 = 1234567890
    var small int32 = int32(big) // 显式转换
    
    // 可能导致精度损失的情况
    var tooBig int64 = 9999999999
    var converted int32 = int32(tooBig) // 溢出,值会改变
    fmt.Printf("原始值: %d, 转换后: %d\n", tooBig, converted)
    
    // 浮点数转整数(截断小数部分)
    var f float64 = 123.987
    var i int = int(f) // 123,小数部分被截断
    fmt.Printf("浮点数: %f, 转整数: %d\n", f, i)
    
    // 整数转浮点数
    var num int = 123456789
    var f32 float32 = float32(num)
    var f64 float64 = float64(num)
    fmt.Printf("整数: %d, float32: %f, float64: %f\n", num, f32, f64)
}

精度损失示例

go 复制代码
func precisionLossDemo() {
    // float32 到 float64 转换
    f32 := float32(1.23456789)
    f64 := float64(f32)
    fmt.Printf("原始 float32: %.8f\n", f32)
    fmt.Printf("转换到 float64: %.8f\n", f64)
    
    // 大整数转浮点数的精度损失
    bigInt := int64(9007199254740993) // 2^53 + 1
    bigFloat := float64(bigInt)
    fmt.Printf("大整数: %d\n", bigInt)
    fmt.Printf("转浮点数: %.0f\n", bigFloat)
    fmt.Printf("是否相等: %v\n", int64(bigFloat) == bigInt)
}

精度考虑

  1. 选择合适的数据类型

    • 一般情况使用 intfloat64
    • 内存敏感场景使用特定大小的类型
    • 金融计算考虑使用整数或 math/big
  2. 避免隐式类型转换

    • Go 要求显式类型转换,这有助于避免意外行为
  3. 注意溢出和精度损失

    • 在类型转换时检查可能的溢出
    • 浮点数比较使用容差而非直接相等
  4. 使用标准库函数

    go 复制代码
    import "math"
    
    // 安全的浮点数比较
    func almostEqual(a, b, tolerance float64) bool {
        return math.Abs(a-b) < tolerance
    }

金融计算

go 复制代码
package main

import (
    "fmt"
    "math/big"
)

func financialCalculation() {
    // 对于金融计算,使用整数表示最小单位(如分)
    type Money int64 // 以分为单位
    
    var price Money = 1999 // 19.99元
    var quantity int = 3
    total := price * Money(quantity)
    
    fmt.Printf("总价: %.2f 元\n", float64(total)/100.0)
    
    // 或者使用 big.Rat 进行精确计算
    priceRat := big.NewRat(1999, 100) // 19.99
    quantityRat := big.NewRat(3, 1)
    totalRat := new(big.Rat).Mul(priceRat, quantityRat)
    
    fmt.Printf("精确总价: %s 元\n", totalRat.FloatString(2))
}

科学计算

go 复制代码
func scientificCalculation() {
    // 对于需要高精度的科学计算
    const preciseValue float64 = 3.14159265358979323846
    
    // 使用 float64 获得更高精度
    circumference := 2 * preciseValue * 10.0
    area := preciseValue * 10.0 * 10.0
    
    fmt.Printf("周长: %.15f\n", circumference)
    fmt.Printf("面积: %.15f\n", area)
    
    // 避免累积误差
    var sum float64
    for i := 0; i < 1000; i++ {
        sum += 0.1
    }
    fmt.Printf("累加 1000 次 0.1: %f\n", sum) // 不是精确的 100.0
    fmt.Printf("误差: %e\n", sum-100.0)
}
相关推荐
期待のcode1 分钟前
Java Object 类
java·开发语言
武子康1 分钟前
大数据-198 KNN 必须先归一化:Min-Max 正确姿势、数据泄露陷阱与 sklearn 落地
大数据·后端·机器学习
Wang's Blog7 分钟前
Lua: 协程编程详解之从基础到多任务处理与应用实战
开发语言·lua
笙枫12 分钟前
LangGraph Agent 架构基础:从概念到第一个可运行的Agent
开发语言·架构·php
李拾叁的摸鱼日常13 分钟前
Java Optional 最佳实践+注意事项+避坑指南
java·后端·面试
啊哈灵机一动20 分钟前
手把手实现 Gin + Socket.IO 实时聊天功能
后端
qq_124987075320 分钟前
基于微信小程序的科技助农系统的设计与实现(源码+论文+部署+安装)
java·大数据·spring boot·后端·科技·微信小程序·毕业设计
狂奔小菜鸡21 分钟前
Day35 | Java多线程入门
java·后端·java ee
哈哈老师啊29 分钟前
Springboot新冠检测信息管理系统10m6v(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
csbysj202030 分钟前
DOM 验证
开发语言