Skip to content

概述

math 包 提供了基本的常量和数学函数, 主要用于浮点数计算,这个包不保证在不同架构上的计算结果完全相同

常量

go
package main

import (
	"fmt"
	"math"
)

func main() {
	// 圆周率
	fmt.Println("PI:", math.Pi)

	// 32位浮点数最大值/32位浮点数最小值
	fmt.Println("MaxFloat32:", math.MaxFloat32)
	fmt.Println("SmallestNonzeroFloat32:", math.SmallestNonzeroFloat32)

	// 64位浮点数最大值/最小值
	fmt.Println("MaxFloat64:", math.MaxFloat64)
	fmt.Println("SmallestNonzeroFloat64:", math.SmallestNonzeroFloat64)

	// int 类型最大值/最小值
	fmt.Println("MaxInt:", math.MaxInt)
	fmt.Println("MinInt:", math.MinInt)

	// int8 类型最大值/最小值
	fmt.Println("MaxInt8:", math.MaxInt8)
	fmt.Println("MinInt8:", math.MinInt8)

	// int16 类型最大值/最小值
	fmt.Println("MaxInt16:", math.MaxInt16)
	fmt.Println("MinInt16:", math.MinInt16)

	// int32 类型最大值/最小值
	fmt.Println("MaxInt32:", math.MaxInt32)
	fmt.Println("MinInt32:", math.MinInt32)

	// int64 类型最大值/最小值
	fmt.Println("MaxInt64:", math.MaxInt64)
	fmt.Println("MinInt64:", math.MinInt64)

	// 无符号类型最大值
	// maxUint8/maxUint16/maxUint32/maxUint64
	fmt.Println("MaxUint8:", math.MaxUint8)
	fmt.Println("MaxUint16:", math.MaxUint16)
	fmt.Println("MaxUint32:", math.MaxUint32)
	// fmt.Println("MaxUint64:", math.MaxUint64)
}

常用方法

函数说明
Abs(x)返回x的绝对值
Max(x, y)返回x和y中的较大值
Min(x, y)返回x和y中的较小值
Mod(x, y)返回x除以y的浮点余数(余数符号与x相同)
Remainder(x, y)返回IEEE 754标准的浮点余数(余数符号与x/y最接近的整数差相关)
Dim(x, y)返回max(x-y, 0)
Pow(x, y)返回x的y次幂
Sqrt(x)返回x的平方根
Cbrt(x)返回x的立方根
Hypot(p, q)返回sqrt(p²+q²),避免计算过程中的溢出
Sin(x)返回x的正弦值(x为弧度)
Cos(x)返回x的余弦值(x为弧度)
Tan(x)返回x的正切值(x为弧度)
Asin(x)返回x的反正弦值(结果范围在[-π/2, π/2])
Acos(x)返回x的反余弦值(结果范围在[0, π])
Atan(x)返回x的反正切值(结果范围在[-π/2, π/2])
Atan2(y, x)返回y/x的反正切值,考虑象限(结果范围在[-π, π])
Sincos(x)同时返回sin(x)和cos(x),比单独调用两个函数更高效
Sinh(x)返回x的双曲正弦值
Cosh(x)返回x的双曲余弦值
Tanh(x)返回x的双曲正切值
Asinh(x)返回x的反双曲正弦值
Acosh(x)返回x的反双曲余弦值(x≥1)
Atanh(x)返回x的反双曲正切值(-10检查+Inf,sign<0检查-Inf,sign=0检查任一无穷大
NaN()返回IEEE 754定义的"非数字"值
IsNaN(f)检查f是否为NaN
Signbit(x)检查x是否为负数(包括-0,-Inf和负NaN)
Ilogb(x)返回x的二进制指数
Float32bits(f)返回float32值f的IEEE 754二进制表示(位模式)
Float32frombits(b)将IEEE 754二进制表示b转换为float32值
Float64bits(f)返回float64值f的IEEE 754二进制表示(位模式)
Float64frombits(b)将IEEE 754二进制表示b转换为float64值
Nextafter(x, y)返回x朝向y方向的下一个可表示的float64值
Nextafter32(x, y)返回x朝向y方向的下一个可表示的float32值

使用示例

go
package main

import (
	"fmt"
	"math"
)

func main() {
	// 基本数学运算
	fmt.Println("===== 基本数学运算 =====")
	fmt.Printf("Abs(-10.5) = %v\n", math.Abs(-10.5))
	fmt.Printf("Max(15.3, 20.7) = %v\n", math.Max(15.3, 20.7))
	fmt.Printf("Min(15.3, 20.7) = %v\n", math.Min(15.3, 20.7))
	fmt.Printf("Mod(10.5, 3) = %v\n", math.Mod(10.5, 3))       // 10.5除以3的余数
	fmt.Printf("Remainder(10.5, 3) = %v\n", math.Remainder(10.5, 3))
	fmt.Printf("Dim(10, 5) = %v\n", math.Dim(10, 5))          // max(10-5, 0)
	fmt.Printf("Dim(5, 10) = %v\n", math.Dim(5, 10))          // max(5-10, 0)
	fmt.Printf("Pow(2, 3) = %v\n", math.Pow(2, 3))            // 2的3次方
	fmt.Printf("Sqrt(16) = %v\n", math.Sqrt(16))              // 16的平方根
	fmt.Printf("Cbrt(27) = %v\n", math.Cbrt(27))              // 27的立方根
	fmt.Printf("Hypot(3, 4) = %v\n", math.Hypot(3, 4))        // sqrt(3*3 + 4*4)

	// 三角函数(参数为弧度)
	fmt.Println("\n===== 三角函数 =====")
	angle := math.Pi / 4 // 45度
	fmt.Printf("Sin(π/4) = %v\n", math.Sin(angle))
	fmt.Printf("Cos(π/4) = %v\n", math.Cos(angle))
	fmt.Printf("Tan(π/4) = %v\n", math.Tan(angle))
	fmt.Printf("Asin(0.707) = %v\n", math.Asin(0.707))
	fmt.Printf("Acos(0.707) = %v\n", math.Acos(0.707))
	fmt.Printf("Atan(1) = %v\n", math.Atan(1))
	fmt.Printf("Atan2(1, 1) = %v\n", math.Atan2(1, 1)) // 在第一象限

	// 同时计算sin和cos
	s, c := math.Sincos(angle)
	fmt.Printf("Sincos(π/4) = sin:%v, cos:%v\n", s, c)

	// 双曲函数
	fmt.Println("\n===== 双曲函数 =====")
	fmt.Printf("Sinh(1) = %v\n", math.Sinh(1))
	fmt.Printf("Cosh(1) = %v\n", math.Cosh(1))
	fmt.Printf("Tanh(1) = %v\n", math.Tanh(1))
	fmt.Printf("Asinh(1) = %v\n", math.Asinh(1))
	fmt.Printf("Acosh(2) = %v\n", math.Acosh(2))
	fmt.Printf("Atanh(0.5) = %v\n", math.Atanh(0.5))

	// 取整函数
	fmt.Println("\n===== 取整函数 =====")
	fmt.Printf("Ceil(3.14) = %v\n", math.Ceil(3.14))          // 向上取整
	fmt.Printf("Floor(3.99) = %v\n", math.Floor(3.99))        // 向下取整
	fmt.Printf("Trunc(3.75) = %v\n", math.Trunc(3.75))        // 截断小数
	fmt.Printf("Trunc(-3.75) = %v\n", math.Trunc(-3.75))      // 截断小数(负数)
	fmt.Printf("Round(3.5) = %v\n", math.Round(3.5))          // 四舍五入
	fmt.Printf("Round(3.4) = %v\n", math.Round(3.4))          // 四舍五入
	fmt.Printf("RoundToEven(2.5) = %v\n", math.RoundToEven(2.5)) // 四舍五入到最近的偶数
	fmt.Printf("RoundToEven(3.5) = %v\n", math.RoundToEven(3.5)) // 四舍五入到最近的偶数

	// 小数与整数部分
	fmt.Println("\n===== 小数与整数部分 =====")
	intPart, fracPart := math.Modf(12.345)
	fmt.Printf("Modf(12.345) = 整数部分:%v, 小数部分:%v\n", intPart, fracPart)

	frac, exp := math.Frexp(0.75)
	fmt.Printf("Frexp(0.75) = 尾数:%v, 指数:%v (0.75 = %v * 2^%v)\n", frac, exp, frac, exp)

	fmt.Printf("Ldexp(0.75, 2) = %v\n", math.Ldexp(0.75, 2)) // 0.75 * 2^2 = 3

	// 特殊值处理
	fmt.Println("\n===== 特殊值处理 =====")
	fmt.Printf("正无穷大: %v\n", math.Inf(1))
	fmt.Printf("负无穷大: %v\n", math.Inf(-1))
	fmt.Printf("IsInf(+Inf, 1) = %v\n", math.IsInf(math.Inf(1), 1))   // 检查是否为+Inf
	fmt.Printf("IsInf(+Inf, -1) = %v\n", math.IsInf(math.Inf(1), -1)) // 检查是否为-Inf
	fmt.Printf("IsInf(+Inf, 0) = %v\n", math.IsInf(math.Inf(1), 0))   // 检查是否为任一Inf

	// NaN示例
	nan := math.NaN()
	fmt.Printf("NaN = %v\n", nan)
	fmt.Printf("IsNaN(NaN) = %v\n", math.IsNaN(nan))

	// 注意:NaN与任何值(包括自己)比较都不相等
	fmt.Printf("NaN == NaN = %v\n", nan == nan)

	// Signbit检查
	fmt.Printf("Signbit(-5) = %v\n", math.Signbit(-5.0))
	fmt.Printf("Signbit(5) = %v\n", math.Signbit(5.0))
	fmt.Printf("Signbit(-0) = %v\n", math.Signbit(math.Copysign(0, -1))) // 检查负零
	fmt.Printf("Ilogb(8) = %v\n", math.Ilogb(8)) // 8的二进制指数 (2^3=8)

	// 浮点数位操作
	fmt.Println("\n===== 浮点数位操作 =====")
	// Float32bits和Float32frombits
	f32 := float32(3.14159)
	bits32 := math.Float32bits(f32)
	restored32 := math.Float32frombits(bits32)
	fmt.Printf("原始float32: %v\n", f32)
	fmt.Printf("IEEE 754位表示: %b\n", bits32)
	fmt.Printf("恢复后的float32: %v\n", restored32)

	// Float64bits和Float64frombits
	f64 := 2.71828
	bits64 := math.Float64bits(f64)
	restored64 := math.Float64frombits(bits64)
	fmt.Printf("\n原始float64: %v\n", f64)
	fmt.Printf("IEEE 754位表示: %b\n", bits64)
	fmt.Printf("恢复后的float64: %v\n", restored64)

	// Nextafter和Nextafter32
	next64 := math.Nextafter(1.0, 2.0)
	fmt.Printf("\nNextafter(1.0, 2.0) = %v\n", next64)
	fmt.Printf("1.0和Nextafter(1.0, 2.0)之间的差: %.20f\n", next64-1.0)

	next32 := math.Nextafter32(1.0, 2.0)
	fmt.Printf("Nextafter32(1.0, 2.0) = %v\n", next32)
	fmt.Printf("1.0和Nextafter32(1.0, 2.0)之间的差: %.20f\n", float64(next32-1.0))
}

注意事项与 Math 其他包介绍

  1. 精度问题: 浮点运算可能会有精度损失,不要直接比较浮点数是否相等,应该检查差值是否小于一个很小的阈值
  2. 特殊值: 许多数学函数对特定输入(如无穷大、NaN、负数)有特殊处理,使用前应了解其行为
  3. 性能考虑: 三角函数和超越函数(如指数、对数)通常比基本算术运算慢,性能关键的代码应谨慎使用
  4. 架构差异: math包不保证在不同架构上产生bit-identical的结果,对精度要求极高的应用需注意
  5. 整数运算: 对于整数运算,标准库提供了math/bits包,包含位操作相关函数
  6. 大数计算: 对于需要任意精度的计算,应使用math/big包而非标准math包
  7. 复数支持: 复数相关函数位于 math/cmplx 包中, 而非math包
  8. 随机数: 随机数生成在math/rand 包中, 与math包是分开的

Released under the MIT License.