引入

数字是程序里最基本的数据——计数用整数,测量用浮点数,索引、排序、计算全都离不开。Go 的数字类型分整型和浮点型,没有隐式类型转换,不同类型之间必须显式转换。搞清楚每种类型的范围和精度,才能避免溢出和精度丢失。

正文

定义

定义

Go 数字分为整型intint8int64uint8uint64)和浮点型float32float64)。整型用于精确的整数运算,浮点型用于带小数的近似运算。math 包提供常用的数学函数和常量。

语法

// 整型
var a int = 42
var b int64 = 1000000
 
// 浮点型
var pi float64 = 3.14159265
 
// 类型转换
var c float64 = float64(a)
var d int = int(pi)

例子

整型运算

a := 10
b := 3
 
fmt.Println(a + b)   // 13
fmt.Println(a - b)   // 7
fmt.Println(a * b)   // 30
fmt.Println(a / b)   // 3(整数除法,截断小数)
fmt.Println(a % b)   // 1(取余)

整数除法会截断小数10 / 3 结果是 3 而不是 3.333…。要得到小数结果,至少有一个操作数是浮点型。

浮点型运算

a := 10.0
b := 3.0
 
fmt.Println(a / b)   // 3.3333333333333335

浮点运算结果有小数,但精度不是无限的,可能出现尾数不精确的情况。

类型转换

// int 转 float64
i := 42
f := float64(i)  // 42.0
 
// float64 转 int(截断小数部分)
f2 := 3.99
i2 := int(f2)    // 3(不是四舍五入,是直接截断)
 
// int32 转 int64
var a int32 = 100
var b int64 = int64(a)

Go 不会自动转换类型,即使是”安全”的转换(比如 int32int64)也必须显式写。

math 包

import "math"
 
// 常用函数
math.Abs(-3.14)        // 3.14
math.Max(1.5, 2.5)     // 2.5
math.Min(1.5, 2.5)     // 1.5
math.Ceil(3.2)          // 4(向上取整)
math.Floor(3.8)         // 3(向下取整)
math.Round(3.5)         // 4(四舍五入)
math.Sqrt(16)           // 4(平方根)
math.Pow(2, 10)         // 1024(幂运算)
math.Log(math.E)        // 1(自然对数)
 
// 常用常量
math.Pi                 // 3.141592653589793
math.E                  // 2.718281828459045
math.MaxInt64           // int64 最大值
math.MinInt64           // int64 最小值

math 包的函数参数和返回值都是 float64,如果传入的是 int,需要先转成 float64

数字和字符串互转

import "strconv"
 
// 字符串转数字
n, _ := strconv.Atoi("42")         // int
f, _ := strconv.ParseFloat("3.14", 64)  // float64
 
// 数字转字符串
s1 := strconv.Itoa(42)             // "42"
s2 := strconv.FormatFloat(3.14, 'f', 2, 64)  // "3.14"
 
// 用 fmt.Sprintf 也可以
s3 := fmt.Sprintf("%d", 42)        // "42"
s4 := fmt.Sprintf("%.2f", 3.14)    // "3.14"

数字和字符串的转换用 strconv 包最正规,fmt.Sprintf 更灵活但稍微慢一点。

整型溢出

var a int8 = 127
// a = a + 1  // 编译报错:常量溢出
 
var b int8 = 127
b = b + 1  // 运行时 wrap around,b 变成 -128

常量溢出在编译期就会报错,变量溢出在运行时会 wrap around(不会报错)。

常见写法

写法说明
a := 42整型,推断为 int
f := 3.14浮点型,推断为 float64
float64(i)intfloat64
int(f)float64int(截断)
math.Abs(x)绝对值
math.Round(x)四舍五入
math.Sqrt(x)平方根
strconv.Atoi("42")字符串转 int
strconv.Itoa(42)int 转字符串

特点

  • Go 没有隐式类型转换intfloat64 运算时必须统一类型
  • 整数除法截断小数,不是四舍五入
  • float64int截断,不是四舍五入(3.993
  • math 包的函数都接收和返回 float64
  • 常量溢出编译报错,变量溢出运行时 wrap around
  • 整型有不同位宽(8/16/32/64),不同类型之间也需要显式转换
  • strconv 包是数字和字符串互转的标准工具

理解

Go 的数字类型最核心的点是没有隐式转换intfloat64 不能直接运算,int32int64 也不能直接运算,必须显式转换。整数除法截断小数这一点容易踩坑,需要小数的结果记得用浮点数。math 包提供了常用的数学函数,但参数都是 float64,传 int 之前要先转类型。

引出

数字运算的结果经常需要和 true/false 做比较来判断条件。接下来看 Go 布尔值,了解 bool 类型以及比较运算和逻辑运算的用法。