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 file converter 转换格式失败 报错 Error marking filters as finished,如何解决?
  • ¥15 ubuntu系统下挂载磁盘上执行./提示权限不够
  • ¥15 Arcgis相交分析无法绘制一个或多个图形
  • ¥15 关于#r语言#的问题:差异分析前数据准备,报错Error in data[, sampleName1] : subscript out of bounds请问怎么解决呀以下是全部代码:
  • ¥15 seatunnel-web使用SQL组件时候后台报错,无法找到表格
  • ¥15 fpga自动售货机数码管(相关搜索:数字时钟)
  • ¥15 用前端向数据库插入数据,通过debug发现数据能走到后端,但是放行之后就会提示错误
  • ¥30 3天&7天&&15天&销量如何统计同一行
  • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型