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]
}