Source File
rand.go
Belonging Package
math/rand/v2
// Copyright 2009 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// Package rand implements pseudo-random number generators suitable for tasks// such as simulation, but it should not be used for security-sensitive work.//// Random numbers are generated by a [Source], usually wrapped in a [Rand].// Both types should be used by a single goroutine at a time: sharing among// multiple goroutines requires some kind of synchronization.//// Top-level functions, such as [Float64] and [Int],// are safe for concurrent use by multiple goroutines.//// This package's outputs might be easily predictable regardless of how it's// seeded. For random numbers suitable for security-sensitive work, see the// [crypto/rand] package.package randimport (_ // for go:linkname)// A Source is a source of uniformly-distributed// pseudo-random uint64 values in the range [0, 1<<64).//// A Source is not safe for concurrent use by multiple goroutines.type Source interface {Uint64() uint64}// A Rand is a source of random numbers.type Rand struct {src Source}// New returns a new Rand that uses random values from src// to generate other random values.func ( Source) *Rand {return &Rand{src: }}// Int64 returns a non-negative pseudo-random 63-bit integer as an int64.func ( *Rand) () int64 { return int64(.src.Uint64() &^ (1 << 63)) }// Uint32 returns a pseudo-random 32-bit value as a uint32.func ( *Rand) () uint32 { return uint32(.src.Uint64() >> 32) }// Uint64 returns a pseudo-random 64-bit value as a uint64.func ( *Rand) () uint64 { return .src.Uint64() }// Int32 returns a non-negative pseudo-random 31-bit integer as an int32.func ( *Rand) () int32 { return int32(.src.Uint64() >> 33) }// Int returns a non-negative pseudo-random int.func ( *Rand) () int { return int(uint(.src.Uint64()) << 1 >> 1) }// Uint returns a pseudo-random uint.func ( *Rand) () uint { return uint(.src.Uint64()) }// Int64N returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n).// It panics if n <= 0.func ( *Rand) ( int64) int64 {if <= 0 {panic("invalid argument to Int64N")}return int64(.uint64n(uint64()))}// Uint64N returns, as a uint64, a non-negative pseudo-random number in the half-open interval [0,n).// It panics if n == 0.func ( *Rand) ( uint64) uint64 {if == 0 {panic("invalid argument to Uint64N")}return .uint64n()}// uint64n is the no-bounds-checks version of Uint64N.func ( *Rand) ( uint64) uint64 {if is32bit && uint64(uint32()) == {return uint64(.uint32n(uint32()))}if &(-1) == 0 { // n is power of two, can maskreturn .Uint64() & ( - 1)}// Suppose we have a uint64 x uniform in the range [0,2⁶⁴)// and want to reduce it to the range [0,n) preserving exact uniformity.// We can simulate a scaling arbitrary precision x * (n/2⁶⁴) by// the high bits of a double-width multiply of x*n, meaning (x*n)/2⁶⁴.// Since there are 2⁶⁴ possible inputs x and only n possible outputs,// the output is necessarily biased if n does not divide 2⁶⁴.// In general (x*n)/2⁶⁴ = k for x*n in [k*2⁶⁴,(k+1)*2⁶⁴).// There are either floor(2⁶⁴/n) or ceil(2⁶⁴/n) possible products// in that range, depending on k.// But suppose we reject the sample and try again when// x*n is in [k*2⁶⁴, k*2⁶⁴+(2⁶⁴%n)), meaning rejecting fewer than n possible// outcomes out of the 2⁶⁴.// Now there are exactly floor(2⁶⁴/n) possible ways to produce// each output value k, so we've restored uniformity.// To get valid uint64 math, 2⁶⁴ % n = (2⁶⁴ - n) % n = -n % n,// so the direct implementation of this algorithm would be://// hi, lo := bits.Mul64(r.Uint64(), n)// thresh := -n % n// for lo < thresh {// hi, lo = bits.Mul64(r.Uint64(), n)// }//// That still leaves an expensive 64-bit division that we would rather avoid.// We know that thresh < n, and n is usually much less than 2⁶⁴, so we can// avoid the last four lines unless lo < n.//// See also:// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction// https://lemire.me/blog/2016/06/30/fast-random-shuffling, := bits.Mul64(.Uint64(), )if < {:= - %for < {, = bits.Mul64(.Uint64(), )}}return}// uint32n is an identical computation to uint64n// but optimized for 32-bit systems.func ( *Rand) ( uint32) uint32 {if &(-1) == 0 { // n is power of two, can maskreturn uint32(.Uint64()) & ( - 1)}// On 64-bit systems we still use the uint64 code below because// the probability of a random uint64 lo being < a uint32 n is near zero,// meaning the unbiasing loop almost never runs.// On 32-bit systems, here we need to implement that same logic in 32-bit math,// both to preserve the exact output sequence observed on 64-bit machines// and to preserve the optimization that the unbiasing loop almost never runs.//// We want to compute// hi, lo := bits.Mul64(r.Uint64(), n)// In terms of 32-bit halves, this is:// x1:x0 := r.Uint64()// 0:hi, lo1:lo0 := bits.Mul64(x1:x0, 0:n)// Writing out the multiplication in terms of bits.Mul32 allows// using direct hardware instructions and avoiding// the computations involving these zeros.:= .Uint64(), := bits.Mul32(uint32(), ), := bits.Mul32(uint32(>>32), ), := bits.Add32(, , 0)+=if == 0 && < uint32() {:= uint64():= uint32(- % )for == 0 && < {:= .Uint64(), = bits.Mul32(uint32(), ), = bits.Mul32(uint32(>>32), ), = bits.Add32(, , 0)+=}}return}// Int32N returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n).// It panics if n <= 0.func ( *Rand) ( int32) int32 {if <= 0 {panic("invalid argument to Int32N")}return int32(.uint64n(uint64()))}// Uint32N returns, as a uint32, a non-negative pseudo-random number in the half-open interval [0,n).// It panics if n == 0.func ( *Rand) ( uint32) uint32 {if == 0 {panic("invalid argument to Uint32N")}return uint32(.uint64n(uint64()))}const is32bit = ^uint(0)>>32 == 0// IntN returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n).// It panics if n <= 0.func ( *Rand) ( int) int {if <= 0 {panic("invalid argument to IntN")}return int(.uint64n(uint64()))}// UintN returns, as a uint, a non-negative pseudo-random number in the half-open interval [0,n).// It panics if n == 0.func ( *Rand) ( uint) uint {if == 0 {panic("invalid argument to UintN")}return uint(.uint64n(uint64()))}// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0).func ( *Rand) () float64 {// There are exactly 1<<53 float64s in [0,1). Use Intn(1<<53) / (1<<53).return float64(.Uint64()<<11>>11) / (1 << 53)}// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0).func ( *Rand) () float32 {// There are exactly 1<<24 float32s in [0,1). Use Intn(1<<24) / (1<<24).return float32(.Uint32()<<8>>8) / (1 << 24)}// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers// in the half-open interval [0,n).func ( *Rand) ( int) []int {:= make([]int, )for := range {[] =}.Shuffle(len(), func(, int) { [], [] = [], [] })return}// Shuffle pseudo-randomizes the order of elements.// n is the number of elements. Shuffle panics if n < 0.// swap swaps the elements with indexes i and j.func ( *Rand) ( int, func(, int)) {if < 0 {panic("invalid argument to Shuffle")}// Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle// Shuffle really ought not be called with n that doesn't fit in 32 bits.// Not only will it take a very long time, but with 2³¹! possible permutations,// there's no way that any PRNG can have a big enough internal state to// generate even a minuscule percentage of the possible permutations.// Nevertheless, the right API signature accepts an int n, so handle it as best we can.for := - 1; > 0; -- {:= int(.uint64n(uint64( + 1)))(, )}}/** Top-level convenience functions*/// globalRand is the source of random numbers for the top-level// convenience functions.var globalRand = &Rand{src: runtimeSource{}}//go:linkname runtime_rand runtime.randfunc () uint64// runtimeSource is a Source that uses the runtime fastrand functions.type runtimeSource struct{}func (runtimeSource) () uint64 {return runtime_rand()}// Int64 returns a non-negative pseudo-random 63-bit integer as an int64// from the default Source.func () int64 { return globalRand.Int64() }// Uint32 returns a pseudo-random 32-bit value as a uint32// from the default Source.func () uint32 { return globalRand.Uint32() }// Uint64N returns, as a uint64, a pseudo-random number in the half-open interval [0,n)// from the default Source.// It panics if n <= 0.func ( uint64) uint64 { return globalRand.Uint64N() }// Uint32N returns, as a uint32, a pseudo-random number in the half-open interval [0,n)// from the default Source.// It panics if n <= 0.func ( uint32) uint32 { return globalRand.Uint32N() }// Uint64 returns a pseudo-random 64-bit value as a uint64// from the default Source.func () uint64 { return globalRand.Uint64() }// Int32 returns a non-negative pseudo-random 31-bit integer as an int32// from the default Source.func () int32 { return globalRand.Int32() }// Int returns a non-negative pseudo-random int from the default Source.func () int { return globalRand.Int() }// Uint returns a pseudo-random uint from the default Source.func () uint { return globalRand.Uint() }// Int64N returns, as an int64, a pseudo-random number in the half-open interval [0,n)// from the default Source.// It panics if n <= 0.func ( int64) int64 { return globalRand.Int64N() }// Int32N returns, as an int32, a pseudo-random number in the half-open interval [0,n)// from the default Source.// It panics if n <= 0.func ( int32) int32 { return globalRand.Int32N() }// IntN returns, as an int, a pseudo-random number in the half-open interval [0,n)// from the default Source.// It panics if n <= 0.func ( int) int { return globalRand.IntN() }// UintN returns, as a uint, a pseudo-random number in the half-open interval [0,n)// from the default Source.// It panics if n <= 0.func ( uint) uint { return globalRand.UintN() }// N returns a pseudo-random number in the half-open interval [0,n) from the default Source.// The type parameter Int can be any integer type.// It panics if n <= 0.func [ intType]( ) {if <= 0 {panic("invalid argument to N")}return (globalRand.uint64n(uint64()))}type intType interface {~int | ~int8 | ~int16 | ~int32 | ~int64 |~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr}// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0)// from the default Source.func () float64 { return globalRand.Float64() }// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0)// from the default Source.func () float32 { return globalRand.Float32() }// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers// in the half-open interval [0,n) from the default Source.func ( int) []int { return globalRand.Perm() }// Shuffle pseudo-randomizes the order of elements using the default Source.// n is the number of elements. Shuffle panics if n < 0.// swap swaps the elements with indexes i and j.func ( int, func(, int)) { globalRand.Shuffle(, ) }// NormFloat64 returns a normally distributed float64 in the range// [-math.MaxFloat64, +math.MaxFloat64] with// standard normal distribution (mean = 0, stddev = 1)// from the default Source.// To produce a different normal distribution, callers can// adjust the output using://// sample = NormFloat64() * desiredStdDev + desiredMeanfunc () float64 { return globalRand.NormFloat64() }// ExpFloat64 returns an exponentially distributed float64 in the range// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter// (lambda) is 1 and whose mean is 1/lambda (1) from the default Source.// To produce a distribution with a different rate parameter,// callers can adjust the output using://// sample = ExpFloat64() / desiredRateParameterfunc () float64 { return globalRand.ExpFloat64() }
![]() |
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |