使用Golang在特定范围内生成随机的float64数

29
package main

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

func genRandNums(min, max float64) []float64 {
    var randNums []float64
    s := rand.NewSource(time.Now().Unix())
    r := rand.New(s)
    for x := 0; x < 10; x++ {
        // generate random float in range of min and max inclusive, append
        // to randNums and return randNums
    }
    return randNums
}

func main() {
    nums := genRandNums(1.10, 101.98)
    fmt.Println(nums)
}

我曾尝试在网上搜索如何实现此操作,但只找到了如何在一定范围内生成随机整数的方法。是否有办法使用Go stdlib在一定范围内生成随机浮点数?

2个回答

62

使用rand.Float64()方法,可以获得一个[0..1)范围内的随机数,您可以通过下面的代码将其映射到[min..max)范围内:

r := min + rand.Float64() * (max - min)

不要在函数内创建新的rand.Rand和/或rand.Source,只需创建一个全局变量或使用math/rand包中的全局变量。但不要忘记初始化它。

这里是一个示例函数:

func randFloats(min, max float64, n int) []float64 {
    res := make([]float64, n)
    for i := range res {
        res[i] = min + rand.Float64() * (max - min)
    }
    return res
}

使用它:

func main() {
    rand.Seed(time.Now().UnixNano())
    fmt.Println(randFloats(1.10, 101.98, 5))
}

输出结果(在Go Playground上尝试):

[51.43243344285539 51.92791316776663 45.04754409242326 28.77642913403846
    58.21730813384373]

一些注意事项:

  • 在 Go Playground 上的代码将始终生成相同的随机数(时间固定,所以种子很可能总是相同,输出也被缓存)。
  • 以上解决方案对于并发使用是安全的,因为它使用了rand.Float64(),该函数使用全局变量 rand,因此是安全的。如果您使用 rand.NewSource() 创建自己的rand.Rand,那么这将不安全,使用它的randFloats() 同样不安全。

不确定它是否适用于0...1范围 - min + rand.Float64() * (max - min) ==> 0 + rand.Float64() * (1 - 0) --> rand.Float64() * 1 ==> rand.Float64() - PARUS
@PARUS 对于 0..1 范围也是有效的,为什么不会呢?当然,对于 0..1 范围,只需调用和使用 rand.Float64() 就足够了。 - icza

-1

如果你想使用crypto/rand,这里有另一个Go Playground可以生成RandomInt()和RandomFloat()(float使用带有常量精度的RandomInt - 你可以将其作为参数)

Go playground


这个解决方案似乎有点巧妙 - 它将生成浮点数,但它们不会在范围内均匀分布(由于浮点精度)。 - BobHy
正如我之前提到的,如果你想使用crypto/rand而不是math/rand,这个解决方案是可行的。没人提到均匀分布、高斯分布或其他任何分布。顺便说一句,对于float64的任何统计分布都像是无意义的……在你用float64精度生成第二个相同数字之前,你中彩票的机会更大;-) - Jakub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接