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