donglu9872 2016-10-07 21:04
浏览 316
已采纳

如何使用标准库在Go中生成*唯一*随机数

Question: How can I generate a stream of unique random number in Go?

Namely, I want to guarantee there's no duplication in array a using math/rand and/or standard Go library utilities.

func RandomNumberGenerator() *rand.Rand {
    s1 := rand.NewSource(time.Now().UnixNano())
    r1 := rand.New(s1)          
    return r1
}
rng := RandomNumberGenerator()    
N := 10000
for i := 0; i < N; i++ {
    a[i] = rng.Int()
}

There are questions and solutions on how to generate a series of random number in Go, for example, here.

But right now I want to generate a series of random number that does not duplicate with previous value. Is there a standard/recommended way to do it in Go?

My guess is to (1)use permutation or to (2) keep track of previously generated numbers and regenerate a value if it's been generated before.

But solution (1) sounds like an overkill if I only want a few number and (2) sounds very time consuming if I end up generating a long series of random numbers due to collision, and I guess it's also very memory-consuming.


Use Case: To benchmark a Go program with 10K, 100K, 1M pseudo-random number that has no duplications.

  • 写回答

5条回答 默认 最新

  • doujishao8793 2016-10-07 23:01
    关注

    Temporary workaround based on @joshlf's answer

    type UniqueRand struct {
        generated   map[int]bool    //keeps track of
        rng         *rand.Rand      //underlying random number generator
        scope       int             //scope of number to be generated
    }
    
    //Generating unique rand less than N
    //If N is less or equal to 0, the scope will be unlimited
    //If N is greater than 0, it will generate (-scope, +scope)
    //If no more unique number can be generated, it will return -1 forwards
    func NewUniqueRand(N int) *UniqueRand{
        s1 := rand.NewSource(time.Now().UnixNano())
        r1 := rand.New(s1)
        return &UniqueRand{
            generated: map[int]bool{},
            rng:        r1,
            scope:      N,
        }
    }
    
    func (u *UniqueRand) Int() int {
        if u.scope > 0 && len(u.generated) >= u.scope {
            return -1
        }
        for {
            var i int
            if u.scope > 0 {
                i = u.rng.Int() % u.scope
            }else{
                i = u.rng.Int()
            }
            if !u.generated[i] {
                u.generated[i] = true
                return i
            }
        }
    }
    

    Client side code

    func TestSetGet2(t *testing.T) {
        const N = 10000
        for _, mask := range []int{0, -1, 0x555555, 0xaaaaaa, 0x333333, 0xcccccc, 0x314159} {
            rng := NewUniqueRand(2*N)
            a := make([]int, N)
            for i := 0; i < N; i++ {
                a[i] = (rng.Int() ^ mask) << 1
            }
    
            //Benchmark Code
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作