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包詳解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM