【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)
}
相关推荐
ctgu9018 小时前
PyQt5(八):ui设置为可以手动随意拉伸功能
开发语言·qt·ui
L.EscaRC18 小时前
Redisson在Spring Boot中的高并发应用解析
java·spring boot·后端
CVer儿18 小时前
libtorch ITK 部署 nnUNetV2 模型
开发语言
苏三的开发日记18 小时前
MySQL事务隔离级别及S与X锁
后端
阑梦清川18 小时前
claude全面封杀国产IDE,trae已经无法使用claude大模型了
后端
asyxchenchong88818 小时前
OpenLCA、GREET、R语言的生命周期评价方法、模型构建
开发语言·r语言
lzptouch18 小时前
Django项目
后端·python·django
没有梦想的咸鱼185-1037-166318 小时前
【生命周期评价(LCA)】基于OpenLCA、GREET、R语言的生命周期评价方法、模型构建
开发语言·数据分析·r语言
Emrys_18 小时前
🚀 深入理解Java并发“王牌”:ConcurrentHashMap
后端