文章

数学计算

数学计算

包总览

核心功能用途
math基本数学函数三角函数/对数/幂/取整
math/big任意精度算术大整数/大浮点数/有理数
math/rand伪随机数随机数生成
math/cmplx复数运算复数三角函数等
math/bits位操作位计数/旋转/前导零

math 包

import "math"

// 常量
math.Pi       // 3.141592653589793
math.E        // 2.718281828459045
math.Phi      // 1.618033988749895 (黄金比例)
math.Sqrt2    // 1.4142135623730951
math.MaxFloat64  // 1.7976931348623157e+308
math.MaxInt64    // 9223372036854775807
math.MaxInt32    // 2147483647
math.MinInt64    // -9223372036854775808

// 取整
math.Floor(3.7)   // 3.0  向下取整
math.Ceil(3.2)    // 4.0  向上取整
math.Trunc(3.7)   // 3.0  截断小数部分
math.Round(3.5)   // 4.0  四舍五入(.5 远离零)
math.Round(3.4)   // 3.0
math.Round(-3.5)  // -4.0

// 幂与根
math.Sqrt(16)     // 4
math.Cbrt(27)     // 3 (立方根)
math.Pow(2, 10)   // 1024
math.Pow10(3)     // 1000

// 对数
math.Log(2.718)   // 0.9999 (自然对数 ln)
math.Log2(8)      // 3
math.Log10(1000)  // 3

// 指数
math.Exp(1)       // 2.718 (e^x)
math.Exp2(5)      // 32 (2^x)
math.Expm1(1)     // 1.718 (e^x - 1,精度更好)

// 三角函数(弧度制)
math.Sin(math.Pi/2)   // 1
math.Cos(0)            // 1
math.Tan(0)            // 0
math.Asin(1)           // 1.5707 (π/2)
math.Acos(1)           // 0
math.Atan(1)           // 0.7853 (π/4)
math.Atan2(1, 1)       // 0.7853 (y/x 的反正切)

// 双曲函数
math.Sinh(0)  // 0
math.Cosh(0)  // 1
math.Tanh(0)  // 0

// 最值
math.Max(3.5, 4.2)   // 4.2
math.Min(3.5, 4.2)   // 3.5

// 绝对值与符号
math.Abs(-3.14)      // 3.14
math.Copysign(3.14, -1) // -3.14(用 y 的符号)

// 特殊值判断
math.IsNaN(math.NaN())     // true
math.IsInf(math.Inf(1), 1) // true
math.Signbit(-3.14)        // true(负数)

math/big 包

import "math/big"

// 大整数(超出 int64 范围)
a := big.NewInt(1)
a.Lsh(a, 100)  // 2^100

b := big.NewInt(1)
b.Lsh(b, 200)  // 2^200

// 运算
c := new(big.Int)
c.Add(a, b)       // 加法
c.Sub(a, b)       // 减法
c.Mul(a, b)       // 乘法
c.Quo(a, b)       // 除法(向零取整)
c.Rem(a, b)       // 余数
c.Mod(a, b)       // 模运算(结果符号与除数相同)
c.Exp(a, b, nil)  // 幂运算 a^b
c.GCD(nil, nil, a, b)  // 最大公约数

// 比较
a.Cmp(b)  // -1 (a<b), 0 (a==b), 1 (a>b)

// 从字符串解析
n := new(big.Int)
n.SetString("123456789012345678901234567890", 10)  // 十进制

// 大浮点数
f1 := big.NewFloat(3.14)
f2 := big.NewFloat(2.71)
result := new(big.Float).Add(f1, f2)

// 设置精度
f := new(big.Float)
f.SetPrec(200)  // 200 位精度
f.SetString("3.141592653589793238462643383279")

// 有理数
r := big.NewRat(1, 3)  // 1/3
r.Add(r, big.NewRat(1, 6))  // 1/3 + 1/6 = 1/2

big.Int 典型应用:加密

// RSA 计算中的大数运算
p := new(big.Int)
p.SetString("61", 10)      // 质数 p
q := new(big.Int)
q.SetString("53", 10)      // 质数 q

n := new(big.Int).Mul(p, q)  // n = p * q = 3233

phi := new(big.Int)
phi.Mul(
    new(big.Int).Sub(p, big.NewInt(1)),
    new(big.Int).Sub(q, big.NewInt(1)),
)  // φ(n) = (p-1)(q-1) = 3120

e := big.NewInt(17)
d := new(big.Int)
d.ModInverse(e, phi)  // d = e^(-1) mod φ(n)

// 加密: c = m^e mod n
m := big.NewInt(65)  // 明文
c := new(big.Int).Exp(m, e, n)

// 解密: m = c^d mod n
decrypted := new(big.Int).Exp(c, d, n)

math/rand 包

import "math/rand"

// Go 1.20+:rand 全局函数自动随机播种,无需手动 Seed
// Go 1.20 之前:需要 rand.Seed(time.Now().UnixNano())

// 随机整数
rand.Int()              // [0, MaxInt64)
rand.Intn(100)          // [0, 100)
rand.Int31n(100)        // [0, 100) int32
rand.Int63n(100)        // [0, 100) int64

// 随机浮点数
rand.Float64()          // [0.0, 1.0)
rand.Float32()          // [0.0, 1.0)

// 随机范围 [min, max]
func RandInt(min, max int) int {
    return rand.Intn(max-min+1) + min
}

// 随机选择
letters := "abcdefghijklmnopqrstuvwxyz0123456789"
func RandString(n int) string {
    b := make([]byte, n)
    for i := range b {
        b[i] = letters[rand.Intn(len(letters))]
    }
    return string(b)
}

// 随机打乱
nums := []int{1, 2, 3, 4, 5}
rand.Shuffle(len(nums), func(i, j int) {
    nums[i], nums[j] = nums[j], nums[i]
})

// 从切片随机选择
idx := rand.Intn(len(slice))

// 正态分布
rand.NormFloat64()  // 标准正态分布 (均值=0, 标准差=1)

// 指数分布
rand.ExpFloat64()   // λ=1 的指数分布

可复现的随机数(测试用)

// 使用确定种子,结果可复现
r := rand.New(rand.NewSource(42))  // 固定种子

r.Intn(100)  // 每次运行结果相同(测试需要可复现性)

// Go 1.22+:rand.NewSource 推荐用 rand.NewPCG
// PCG(Permuted Congruential Generator)统计性更好

随机数安全注意

场景不用原因
游戏/模拟math/rand性能好
UUID 生成math/rand足够随机
密码/tokencrypto/randmath/rand需要密码学安全
密钥生成crypto/randmath/rand防止预测
// crypto/rand:密码学安全随机数
import "crypto/rand"

func SecureRandomBytes(n int) ([]byte, error) {
    b := make([]byte, n)
    _, err := rand.Read(b)
    return b, err
}

func SecureToken(n int) (string, error) {
    b, err := SecureRandomBytes(n)
    if err != nil {
        return "", err
    }
    return base64.URLEncoding.EncodeToString(b), nil
}

math/bits 包

import "math/bits"

// 位计数
bits.OnesCount64(0xFF)        // 8 (1的个数)
bits.OnesCount32(0xF0F0)      // 8

// 前导零
bits.LeadingZeros64(1)        // 63
bits.LeadingZeros32(1)        // 31

// 尾随零
bits.TrailingZeros64(8)       // 3 (8=1000)
bits.TrailingZeros32(0)       // 32

// 位长度
bits.Len64(255)               // 8 (表示 255 需要的位数)

// 旋转
bits.RotateLeft64(0x1, 4)     // 0x10 (左移4位)

// 最高/最低有效位
bits.TrailingZeros8(1)        // 0

// 计算 log2
log2 := bits.Len64(uint64(n)) - 1  // 向下取整的 log2

math/cmplx 包

import "math/cmplx"

// 复数
z := complex(3, 4)    // 3+4i
real(z)                // 3.0
imag(z)                // 4.0

// 复数运算
cmplx.Abs(z)           // 5.0 (|z| = √(3²+4²))
cmplx.Phase(z)         // 0.927 (辐角 atan2(4,3))
r, θ := cmplx.Polar(z) // 极坐标

// 三角函数
cmplx.Sin(z)
cmplx.Cos(z)
cmplx.Exp(z)           // e^z

// 幂与根
cmplx.Sqrt(z)           // 复数平方根
cmplx.Pow(z1, z2)       // z1^z2

常见数学操作封装

// 整数范围限制
func ClampInt(v, min, max int) int {
    if v < min {
        return min
    }
    if v > max {
        return max
    }
    return v
}

// 浮点数范围限制
func ClampFloat64(v, min, max float64) float64 {
    return math.Max(min, math.Min(v, max))
}

// 浮点数相等比较(处理精度问题)
func AlmostEqual(a, b, epsilon float64) bool {
    return math.Abs(a-b) < epsilon
}

// 四舍五入到指定小数位
func RoundToDecimal(v float64, decimal int) float64 {
    multiplier := math.Pow(10, float64(decimal))
    return math.Round(v*multiplier) / multiplier
}

// 百分比计算
func Percentage(part, total float64) float64 {
    if total == 0 {
        return 0
    }
    return (part / total) * 100
}

// 最大公约数
func GCD(a, b int) int {
    for b != 0 {
        a, b = b, a%b
    }
    return a
}

// 最小公倍数
func LCM(a, b int) int {
    return a * b / GCD(a, b)
}

// 判断质数
func IsPrime(n int) bool {
    if n < 2 {
        return false
    }
    if n < 4 {
        return true
    }
    if n%2 == 0 {
        return false
    }
    for i := 3; i*i <= n; i += 2 {
        if n%i == 0 {
            return false
        }
    }
    return true
}

// 斐波那契数列
func Fibonacci(n int) int {
    if n <= 1 {
        return n
    }
    a, b := 0, 1
    for i := 2; i <= n; i++ {
        a, b = b, a+b
    }
    return b
}