Go 语言标准库之 math & math/rand 包

math 包提供了基本的数学常数和数学函数,math/rand包实现了伪随机数生成器, 本文对 math 和math/rand包的常用操作进行介绍。

math 包

常用常数

☕️ 数学常数

const (
    E   = 2.71828182845904523536028747135266249775724709369995957496696763
    Pi  = 3.14159265358979323846264338327950288419716939937510582097494459
    Phi = 1.61803398874989484820458683436563811772030917980576286213544862

    Sqrt2   = 1.41421356237309504880168872420969807856967187537694807317667974
    SqrtE   = 1.64872127070012814684865078781416357165377610071014801157507931
    SqrtPi  = 1.77245385090551602729816748334114518279754945612238712821380779
    SqrtPhi = 1.27201964951406896425242246173749149171560804184009624861664038

    Ln2    = 0.693147180559945309417232121458176568075500134360255254120680009
    Log2E  = 1 / Ln2
    Ln10   = 2.30258509299404568401799145468436420760110148862877297603332790
    Log10E = 1 / Ln10
)

⭐️ 浮点数的取值极限

// Max 是该类型所能表示的最大有限值;SmallestNonzero 是该类型所能表示的最小非零正数值
const (
    MaxFloat32             = 0x1p127 * (1 + (1 - 0x1p-23)) // 3.40282346638528859811704183484516925440e+38
    SmallestNonzeroFloat32 = 0x1p-126 * 0x1p-23            // 1.401298464324817070923729583289916131280e-45

    MaxFloat64             = 0x1p1023 * (1 + (1 - 0x1p-52)) // 1.79769313486231570814527423731704356798070e+308
    SmallestNonzeroFloat64 = 0x1p-1022 * 0x1p-52            // 4.9406564584124654417656879286822137236505980e-324
)

✏️ 整数的取值极限

const (
    intSize = 32 << (^uint(0) >> 63) // 32 or 64

    MaxInt    = 1<<(intSize-1) - 1
    MinInt    = -1 << (intSize - 1)
    MaxInt8   = 1<<7 - 1
    MinInt8   = -1 << 7
    MaxInt16  = 1<<15 - 1
    MinInt16  = -1 << 15
    MaxInt32  = 1<<31 - 1
    MinInt32  = -1 << 31
    MaxInt64  = 1<<63 - 1
    MinInt64  = -1 << 63
    MaxUint   = 1<<intSize - 1
    MaxUint8  = 1<<8 - 1
    MaxUint16 = 1<<16 - 1
    MaxUint32 = 1<<32 - 1
    MaxUint64 = 1<<64 - 1
)

常用函数

// 三角函数
func Sin(x float64) float64               // 正弦函数
func Asin(x float64) float64              // 反正弦函数
func Sinh(x float64) float64              // 双曲正弦
func Asinh(x float64) float64             // 反双曲正弦
func Sincos(x float64) (sin, cos float64) // 一次性返回 sin,cos
func Cos(x float64) float64               // 余弦函数
func Acos(x float64) float64              // 反余弦函数
func Cosh(x float64) float64              // 双曲余弦
func Acosh(x float64) float64             // 反双曲余弦
func Tan(x float64) float64               // 正切函数
func Atan(x float64) float64              // 反正切函数
func Atan2(y, x float64) float64          // 反正切函数
func Tanh(x float64) float64              // 双曲正切
func Atanh(x float64) float64             // 反双曲正切

// 幂次函数
func Cbrt(x float64) float64   // 立方根函数
func Pow(x, y float64) float64 // x 的幂函数
func Pow10(e int) float64      // 10 根的幂函数
func Sqrt(x float64) float64   // 平方根
func Log(x float64) float64    // 对数函数
func Log10(x float64) float64  // 10 为底的对数函数
func Log2(x float64) float64   // 2 为底的对数函数
func Log1p(x float64) float64  // log(1 + x)
func Logb(x float64) float64   // 相当于 log2(x) 的绝对值
func Ilogb(x float64) int      // 相当于 log2(x) 的绝对值的整数部分
func Exp(x float64) float64    // 指数函数
func Exp2(x float64) float64   // 2 为底的指数函数
func Expm1(x float64) float64  // Exp(x) - 1

// 特殊函数
func Inf(sign int) float64           // 如果 sign>=0 函数返回正无穷大,否则返回负无穷大
func IsInf(f float64, sign int) bool //  如果 sign > 0,f 是正无穷大时返回真;如果 sign < 0,f 是负无穷大时返回真;sign == 0 则 f 是两种无穷大时都返回真
func NaN() float64                   // 返回一个 NaN(Not A Number)值
func IsNaN(f float64) (is bool)      // 是否是 NaN 值
func Hypot(p, q float64) float64     // 计算直角三角形的斜边长

// 类型转化函数
func Float32bits(f float32) uint32     // float32 和 unit32 的转换
func Float32frombits(b uint32) float32 // uint32 和 float32 的转换
func Float64bits(f float64) uint64     // float64 和 uint64 的转换
func Float64frombits(b uint64) float64 // uint64 和 float64 的转换

// 其他函数
func Abs(x float64) float64                       // 绝对值函数
func Ceil(x float64) float64                      // 向上取整
func Floor(x float64) float64                     // 向下取整
func Trunc(x float64) float64                     // 截取函数(返回 x 的整数部分)
func Mod(x, y float64) float64                    // 取模,结果的正负号和 x 相同
func Remainder(x, y float64) float64              // 取余运算
func Modf(f float64) (int float64, frac float64)  // 分解 f,以得到 f 的整数和小数部分
func Frexp(f float64) (frac float64, exp int)     // 分解 f,得到 f 的位数和指数
func Max(x, y float64) float64                    // 取大值
func Min(x, y float64) float64                    // 取小值
func Dim(x, y float64) float64                    // 复数的维数
func J0(x float64) float64                        // 0 阶贝塞尔函数
func J1(x float64) float64                        // 1 阶贝塞尔函数
func Jn(n int, x float64) float64                 // n 阶贝塞尔函数
func Y0(x float64) float64                        // 第二类贝塞尔函数 0 阶
func Y1(x float64) float64                        // 第二类贝塞尔函数 1 阶
func Yn(n int, x float64) float64                 // 第二类贝塞尔函数 n 阶
func Erf(x float64) float64                       // 误差函数
func Erfc(x float64) float64                      // 余补误差函数
func Copysign(x, y float64) float64               // 以 y 的符号返回 x 值
func Signbit(x float64) bool                      // 获取 x 的符号
func Gamma(x float64) float64                     // 伽玛函数
func Lgamma(x float64) (lgamma float64, sign int) // 伽玛函数的自然对数
func Ldexp(frac float64, exp int) float64         // value 乘以 2 的 exp 次幂
func Nextafter(x, y float64) (r float64)          // 返回参数 x 在参数 y 方向上可以表示的最接近的数值,若 x 等于 y,则返回 x
func Nextafter32(x, y float32) (r float32)        // 返回参数 x 在参数 y 方向上可以表示的最接近的数值,若 x 等于 y,则返回 x

📚 示例代码

package main

import (
    "fmt"
    "math"
)

func main() {
    fmt.Println(math.IsNaN(math.NaN()))     // true
    fmt.Println(math.IsInf(math.Inf(1), 1)) // true
    fmt.Println(math.Ceil(1.000001))        // 2
    fmt.Println(math.Floor(1.999999))       // 1
    fmt.Println(math.Trunc(1.999999))       // 1
    fmt.Println(math.Abs(-1.3))             // 1.3
    fmt.Println(math.Max(-1.3, 0))          // 0
    fmt.Println(math.Min(-1.3, 0))          // -1.3
    fmt.Println(math.Dim(-12, 19))          // 0
    fmt.Println(math.Mod(9, 4))             // 1
    fmt.Println(math.Sqrt(9))               // 3
    fmt.Println(math.Cbrt(8))               // 2
    fmt.Println(math.Hypot(3, 4))           // 5
    fmt.Println(math.Sin(90))               // 0.893996663600558
    fmt.Println(math.Cos(0))                // 1
    fmt.Println(math.Tan(45))               // 1.6197751905438615
    fmt.Println(math.Log(1))                // 0
    fmt.Println(math.Log2(16))              // 4
    fmt.Println(math.Log10(1000))           // 3
    fmt.Println(math.Pow(2, 8))             // 256
    fmt.Println(math.Pow10(2))              // 100
}

math/rand 包

Rand 结构体生成随机数

Go 语言中生成随机数需要一个结构体实例Rand,该结构体字段都是隐藏或非导出,只能通过其它函数构建,该结构体定义如下:

// Rand 生成服从多种分布的随机数
type Rand struct {
    src Source
    s64 Source64 // non-nil if src is source64

    // readVal contains remainder of 63-bit integer used for bytes
    // generation during most recent Read call.
    // It is saved so next Read call can start where the previous
    // one finished.
    readVal int64
    // readPos indicates the number of low-order bytes of readVal
    // that are still valid.
    readPos int8
}

// Source 代表一个生成均匀分布在范围 [0, 1<<63) 的 int64 值的(伪随机的)资源
type Source interface {
    Int63() int64
    Seed(seed int64)
}

✌ 常用的方法

// 使用给定的种子创建一个伪随机资源
func NewSource(seed int64) Source

// 返回一个使用 src 生产的随机数来生成其他各种分布的随机数值的 *Rand
func New(src Source) *Rand

// 使用给定的 seed 来初始化生成器到一个确定的状态
func (r *Rand) Seed(seed int64)

// 返回一个非负的伪随机 int 值
func (r *Rand) Int() int

// 返回一个 int32 类型的非负的 31 位伪随机数
func (r *Rand) Int31() int32

// 返回一个 int64 类型的非负的 63 位伪随机数
func (r *Rand) Int63() int64

// 返回一个 uint32 类型的非负的 32 位伪随机数
func (r *Rand) Uint32() uint32

// 返回一个 uint64 类型的非负的 64 位伪随机数
func (r *Rand) Uint64() uint64

// 返回一个取值范围在 [0,n) 的伪随机 int 值,如果 n <= 0 会 panic
func (r *Rand) Intn(n int) int

// 返回一个取值范围在 [0,n) 的伪随机 int32 值,如果 n <= 0 会 panic
func (r *Rand) Int31n(n int32) int32

// 返回一个取值范围在 [0,n) 的伪随机 int64 值,如果 n <= 0 会 panic
func (r *Rand) Int63n(n int64) int64

// 返回一个取值范围在 [0.0, 1.0) 的伪随机 float32 值
func (r *Rand) Float32() float32

// 返回一个取值范围在 [0.0, 1.0) 的伪随机 float64 值
func (r *Rand) Float64() float64

// 返回一个有 n 个元素的,[0,n) 范围内整数的伪随机排列的切片
func (r *Rand) Perm(n int) []int

✍ 示例代码

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    // 使用当前时间的纳秒作为随机数种子,生成一个 Rand
    random := rand.New(rand.NewSource(time.Now().UnixNano()))

    // 产生随机数
    fmt.Println(random.Int())        // 5700972045344779666
    fmt.Println(random.Int31())      // 502460982
    fmt.Println(random.Int63())      // 4492647983110733892
    fmt.Println(random.Uint32())     // 3078962887
    fmt.Println(random.Uint64())     // 16976507327111900586
    fmt.Println(random.Intn(1000))   // 978
    fmt.Println(random.Int31n(1000)) // 864
    fmt.Println(random.Int63n(1000)) // 585
    fmt.Println(random.Float32())    // 0.23783964
    fmt.Println(random.Float64())    // 0.6970960282910409
    fmt.Println(random.Perm(5))      // [4 0 3 2 1]
}

其它生成随机数函数

Go 语言在math/rand包中内置一个 Rand 对象 globalRand,并将该对象的方法包装为math/rand包的公开函数,我们可以直接调用这些公开函数生成随机数。

// globalRand 对象是一个随机数种子默认为 1 的随机数生成器
var globalRand = New(&lockedSource{src: NewSource(1).(*rngSource)})

💡 常用的函数

// 下面函数实际上是调用 globalRand 对象的方法生成随机数
// 设置随机数种子,如果不设置,默认为 1 
func Seed(seed int64)

// 返回一个非负的伪随机 int 值
func Int() int

// 返回一个 int32 类型的非负的 31 位伪随机数
func Int31() int32

// 返回一个 int64 类型的非负的 63 位伪随机数
func Int63() int64

// 返回一个 uint32 类型的非负的 32 位伪随机数
func Uint32() uint32

// 返回一个 uint64 类型的非负的 64 位伪随机数
func Uint64() uint64

// 返回一个取值范围在 [0,n) 的伪随机 int 值,如果 n <= 0 会 panic
func Intn(n int) int

// 返回一个取值范围在 [0,n) 的伪随机 int32 值,如果 n <= 0 会 panic
func Int31n(n int32) int32

// 返回一个取值范围在 [0, n) 的伪随机 int64 值,如果 n<=0 会 panic
func Int63n(n int64) int64

// 返回一个取值范围在 [0.0, 1.0) 的伪随机 float32 值
func Float32() float32

// 返回一个取值范围在 [0.0, 1.0) 的伪随机 float64 值
func Float64() float64

// 返回一个有 n 个元素的,[0,n) 范围内整数的伪随机排列的切片
func Perm(n int) []int

☕️ 示例代码

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    // 使用当前时间的纳秒作为随机数种子
    rand.Seed(time.Now().UnixNano())

    // 产生随机数
    fmt.Println(rand.Int())        // 7696473600670801125
    fmt.Println(rand.Int31())      // 101522707
    fmt.Println(rand.Int63())      // 4586127142344489967
    fmt.Println(rand.Uint32())     // 2654323971
    fmt.Println(rand.Uint64())     // 818444552739191252
    fmt.Println(rand.Intn(1000))   // 404
    fmt.Println(rand.Int31n(1000)) // 839
    fmt.Println(rand.Int63n(1000)) // 670
    fmt.Println(rand.Float32())    // 0.045811735
    fmt.Println(rand.Float64())    // 0.22264400405223367
    fmt.Println(rand.Perm(5))      // [1 4 2 3 0]
}

参考

  1. go math/rand包详解
posted @ 2021-12-06 11:09  呵呵233  阅读(638)  评论(0编辑  收藏  举报