在 Go 中生成随机数

发布于 2024-11-11 18:52:13 字数 497 浏览 5 评论 0原文

我试图在 Go 中生成随机数(整数),但无济于事。我在 crypto/rand< 中找到了 rand 包/a>,这似乎是我想要的,但我无法从文档中得知如何使用它。这就是我现在正在尝试的:

    b := []byte{}
    something, err := rand.Read(b)
    fmt.Printf("something = %v\n", something)
    fmt.Printf("err = %v\n", err)

但不幸的是,这总是输出:

    something = 0
    err = <nil>

有没有办法解决这个问题,以便它实际上生成随机数?或者,有没有办法设置生成的随机数的上限?

I am trying to generate random numbers (integers) in Go, to no avail. I found the rand package in crypto/rand, which seems to be what I want, but I can't tell from the documentation how to use it. This is what I'm trying right now:

    b := []byte{}
    something, err := rand.Read(b)
    fmt.Printf("something = %v\n", something)
    fmt.Printf("err = %v\n", err)

But unfortunately this always outputs:

    something = 0
    err = <nil>

Is there a way to fix this so that it actually generates random numbers? Alternatively, is there a way to set the upper bound on the random numbers this generates?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

芯好空 2024-11-18 18:52:13

根据您的用例,另一个选项是 math/rand 包。如果您生成的数字需要完全不可预测,请不要这样做。不过,如果您需要获得可重现的结果,它会很有帮助 - 只需传递您第一次传递的相同种子即可。

这是经典的“用当前时间为生成器播种并生成一个数字”程序:

package main

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

func main() {
    rand.Seed(time.Now().Unix())
    fmt.Println(rand.Int())
}

Depending on your use case, another option is the math/rand package. Don't do this if you're generating numbers that need to be completely unpredictable. It can be helpful if you need to get results that are reproducible, though -- just pass in the same seed you passed in the first time.

Here's the classic "seed the generator with the current time and generate a number" program:

package main

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

func main() {
    rand.Seed(time.Now().Unix())
    fmt.Println(rand.Int())
}
油饼 2024-11-18 18:52:13

crypto/rand 仅提供随机数据的二进制流,但您可以使用 encoding/binary 从中读取整数:

package main

import "encoding/binary"
import "crypto/rand"

func main() {
    var n int32
    binary.Read(rand.Reader, binary.LittleEndian, &n)
    println(n)
}

crypto/rand provides only binary stream of random data, but you can read integers from it using encoding/binary:

package main

import "encoding/binary"
import "crypto/rand"

func main() {
    var n int32
    binary.Read(rand.Reader, binary.LittleEndian, &n)
    println(n)
}
城歌 2024-11-18 18:52:13

自2012年4月1日起,lang的稳定版本发布后,您可以执行以下操作:

package main

导入“fmt” 导入“时间” 导入“数学/兰特”

func main() { rand.Seed(time.Now().UnixNano()) // 以纳秒为单位的当前时间作为种子 fmt.Println(rand.Intn(100)) // 这给你一个最大但不包括 100 的 int }

As of 1 april 2012, after the release of the stable version of the lang, you can do the following:

package main

import "fmt" import "time" import "math/rand"

func main() { rand.Seed(time.Now().UnixNano()) // takes the current time in nanoseconds as the seed fmt.Println(rand.Intn(100)) // this gives you an int up to but not including 100 }

霞映澄塘 2024-11-18 18:52:13

您还可以开发自己的随机数生成器,可能基于简单的“荒岛 PRNG”(线性同余生成器)。另外,请查找 L'Ecuyer (1999)、Mersenne Twister 或 Tausworthe 生成器...

https:// en.wikipedia.org/wiki/Pseudorandom_number_generator

(避免 RANDU,它在 1960 年代很流行,但是生成的随机数落在 3 空间中的 15 个超平面上)。

package pmPRNG

import "errors"

const (
    Mersenne31 = 2147483647 // = 2^31-1
    Mersenne31Inv = 1.0 / 2147483647.0 // = 4.656612875e-10

    // a = 16807
    a = 48271
)

// Each stream gets own seed
type PRNGStream struct {
    state int
}

func PRNGStreamNew(seed int) *PRNGStream {
    prng := (&PRNGStream{})
    prng.SetSeed(seed)
    return prng
}

// enforce seed in [1, 2^31-1]
func (r*PRNGStream) SetSeed(seed int) error {
    var err error

    if seed < 1 || seed > Mersenne31 {
        err = errors.New("Seed OOB")
    }

    if seed > Mersenne31 { seed = seed % Mersenne31 }
    if seed < 1 { seed = 1 }
    r.state = seed

    return err
}

// Dig = Park-Miller DesertIslandGenerator
// integer seed in [1, 2^31-1]
func (r*PRNGStream) Dig(seed int) float32 {
    xprev := r.state // x[i-1]
    xnext := (a * xprev) % Mersenne31 // x[i] = (a*x[i-1])%m
    r.state = xnext // x[i-1] = x[i]
    Ri := float32(xnext) * Mersenne31Inv // convert Ui to Ri
    return Ri
}


func (r*PRNGStream) Rand() float32 {
    r.state = (uint64_t)*r.state * Multby % 0x7fffffff
    return float32(r.state) * Mersenne31Inv
}

一些相关链接:

https://en.wikipedia.org/wiki/Lehmer_random_number_generator

使用此函数来更新您的 x[i+1],而不是上面的函数,
val = ((状态 * 1103515245) + 12345) & 0x7ffffffff 0x7fffffff
(基本上,a、c、m 的值不同)

https://www.redhat.com/en/blog/understanding-random-number-generators-and-their-limitations-linux

https://www.iro.umontreal.ca/~lecuyer/myftp/论文/handstat.pdf

https://www.math.utah.edu/~alfeld/Random/Random.html

https://learn.microsoft.com/en-us/archive/msdn-magazine/2016/august/test-run-lightweight-random-number- Generation

You can also develop your own random number generator, perhaps based upon a simple "desert island PRNG", a Linear Congruential Generator. Also, look up L'Ecuyer (1999), Mersenne Twister, or Tausworthe generator...

https://en.wikipedia.org/wiki/Pseudorandom_number_generator

(Avoid RANDU, it was popular in the 1960's, but the random numbers generated fall on 15 hyperplanes in 3-space).

package pmPRNG

import "errors"

const (
    Mersenne31 = 2147483647 // = 2^31-1
    Mersenne31Inv = 1.0 / 2147483647.0 // = 4.656612875e-10

    // a = 16807
    a = 48271
)

// Each stream gets own seed
type PRNGStream struct {
    state int
}

func PRNGStreamNew(seed int) *PRNGStream {
    prng := (&PRNGStream{})
    prng.SetSeed(seed)
    return prng
}

// enforce seed in [1, 2^31-1]
func (r*PRNGStream) SetSeed(seed int) error {
    var err error

    if seed < 1 || seed > Mersenne31 {
        err = errors.New("Seed OOB")
    }

    if seed > Mersenne31 { seed = seed % Mersenne31 }
    if seed < 1 { seed = 1 }
    r.state = seed

    return err
}

// Dig = Park-Miller DesertIslandGenerator
// integer seed in [1, 2^31-1]
func (r*PRNGStream) Dig(seed int) float32 {
    xprev := r.state // x[i-1]
    xnext := (a * xprev) % Mersenne31 // x[i] = (a*x[i-1])%m
    r.state = xnext // x[i-1] = x[i]
    Ri := float32(xnext) * Mersenne31Inv // convert Ui to Ri
    return Ri
}


func (r*PRNGStream) Rand() float32 {
    r.state = (uint64_t)*r.state * Multby % 0x7fffffff
    return float32(r.state) * Mersenne31Inv
}

A few relevant links:

https://en.wikipedia.org/wiki/Lehmer_random_number_generator

You might use this function to update your x[i+1], instead of the one above,
val = ((state * 1103515245) + 12345) & 0x7fffffff
(basically, different values of a, c, m)

https://www.redhat.com/en/blog/understanding-random-number-generators-and-their-limitations-linux

https://www.iro.umontreal.ca/~lecuyer/myftp/papers/handstat.pdf

https://www.math.utah.edu/~alfeld/Random/Random.html

https://learn.microsoft.com/en-us/archive/msdn-magazine/2016/august/test-run-lightweight-random-number-generation

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文