随机数

[toc]


我们应用中的随机数

  1. 抽奖,大转盘
  2. 我们经常接触的验证码
  3. 密码找回
  4. go中select的公平保证
  5. 再然后https通信中的秘钥生成
  6. 还有游戏中爆装备的概率等

你以为的随机是真的随机吗

如果我们试着在程序开始的生成一个随机数,你会发现每次都是一样的。

我们可以准确的判断出随机数是什么。

所以这也就是我们经常说的伪随机数。

那有没有真正的随机数呢,比如我们可以再一开始生成一个seed,然后再去生成随机数,这样每次都不一样了,但是这样就是真正的随机了吗。举一个极端的例子,你用随机数生成密码,种子是时间戳,而我恰好知道了你程序开始的时间,那么我就可以得到你的密码序列。

那再进一步呢,还没有别的办法,有的。我们可以根据周边物理条件来生成随机数。比如温度或者声音的变化,用户是键盘和鼠标输入等。 目前这些已经集成在部分硬件上了。

对应到我们go中呢,真随机是 crypto/rand,伪随机是math/rand,虽然真随机更好,但是我们不是需要再任何地方都用真随机的。因为有的时候安全并不重要,其次真随机性能会差很多。

// 伪随机
func Prng() int64 {
    return rand.Int63()
}

//真随机
func SecureRng() int64 {
    v, _ := srand.Int(srand.Reader, big.NewInt(math.MaxInt64))
    return v.Int64()
}

进行性能测试如下

➜  rand go test -run=none -bench=BenchmarkRng  -count=10  
goos: darwin
goarch: amd64
pkg: lucas/code/rand
BenchmarkRng/PRNG-8             79132172                14.7 ns/op
BenchmarkRng/PRNG-8             81666558                14.8 ns/op
BenchmarkRng/PRNG-8             72479173                14.8 ns/op
BenchmarkRng/PRNG-8             79032494                14.8 ns/op
BenchmarkRng/PRNG-8             75016249                15.0 ns/op
BenchmarkRng/PRNG-8             77717745                14.9 ns/op
BenchmarkRng/PRNG-8             80101124                14.8 ns/op
BenchmarkRng/PRNG-8             76762986                14.8 ns/op
BenchmarkRng/PRNG-8             77451264                14.7 ns/op
BenchmarkRng/PRNG-8             75431827                14.8 ns/op
BenchmarkRng/SRNG-8              6292308               179 ns/op
BenchmarkRng/SRNG-8              6467247               178 ns/op
BenchmarkRng/SRNG-8              6467979               178 ns/op
BenchmarkRng/SRNG-8              6464542               178 ns/op
BenchmarkRng/SRNG-8              6239452               179 ns/op
BenchmarkRng/SRNG-8              6433585               177 ns/op
BenchmarkRng/SRNG-8              6494451               178 ns/op
BenchmarkRng/SRNG-8              6401463               179 ns/op
BenchmarkRng/SRNG-8              6466090               179 ns/op
BenchmarkRng/SRNG-8              6501558               178 ns/op

可见差了1个量级。所以我们应该有个这样的结论就是随机数用我们最合适的。

随机数怎么生成的呢

<img src="http://picgo.vipkk.work/20200517013900.png" alt="image-20200517013900312" style="zoom:50%;" />

简单来说就是我们维护了一个随机数表,然后每次调用从表里取一个进行生成,然后用生成的值更新表里的值。

具体的算法

  1. 线性同余法(c和java内部是这样实现的)

    <img src="http://picgo.vipkk.work/20200517014210.png" alt="image-20200517014210305" style="zoom:50%;" />

  2. go的实现(继承于plan9,也没有具体的名称了)

    src/math/rand/rng.go

    /*
     * Uniform distribution
     *
     * algorithm by
     * DP Mitchell and JA Reeds
     */
    

一个细节

无论是go还是c实现上我们都需要更新内部状态,这也就是说rand生成是加锁的。

具体案例分析

  1. 公平的select

    channel 之间的选择

    1. shuffle算法

      如何保证公平

  2. [生成一个字符串][1]

    ➜  go test -run=none -bench=BenchmarkRandStr -benchmem
    goos: darwin
    goarch: amd64
    pkg: lucas/code/rand
    BenchmarkRandStr/str1-8                   504416              2230 ns/op             224 B/op          2 allocs/op
    BenchmarkRandStr/str2-8                   587556              1946 ns/op             224 B/op          2 allocs/op
    BenchmarkRandStr/str3-8                  1996708               583 ns/op             224 B/op          2 allocs/op
    BenchmarkRandStr/str4-8                  1859163               690 ns/op             112 B/op          1 allocs/op
    BenchmarkRandStr/str5-8                  2001969               560 ns/op             112 B/op          1 allocs/op
    PASS
    ok      lucas/code/rand 9.819s
    
    
    image-20200517022405429
    1. 合适的function
    2. 结合实际的mask
    3. 内存减少

随机数的定义

  1. 随机性
  2. 不可预测性
  3. 不可重现性

这三个是依次递进的,

<img src="http://picgo.vipkk.work/20200517002229.png" alt="image-20200517002229634" style="zoom:50%;" />

参考资料

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

  2. 随机数安全

  3. https://blog.sqrtthree.com/articles/random-number-in-golang

  4. https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-go

  5. https://www.zhihu.com/question/20222653

  6. shuffle算法

    // 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 (r *Rand) Shuffle(n int, swap func(i, j int)) {
     if n < 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.
     i := n - 1
     for ; i > 1<<31-1-1; i-- {
         j := int(r.Int63n(int64(i + 1)))
         swap(i, j)
     }
     for ; i > 0; i-- {
         j := int(r.int31n(int32(i + 1)))
         swap(i, j)
     }
    }
    

如何评价一个随机数算法的优劣

TODO

C#

<img src="http://picgo.vipkk.work/20200518133248.jpg" alt="img" style="zoom:100%;" />

PHP

img

GO

result1

Other

  1. int64n 与 int64 %n 效果是不一样的
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容