关于python shuffle函数随机性的测试

牌堆=[i for i in range(160)]
弃牌堆=[]
for i in range(len(牌堆)):
    弃牌堆.append(牌堆[i])
import time
import numpy as np
def 洗牌(弃牌堆):
    global 牌堆
    import random
    #random.seed(time.time())
    random.shuffle(弃牌堆)
    #弃牌堆 = np.random.permutation(弃牌堆)
    return 弃牌堆
重合次数=[]
for i in range(len(牌堆)):
    重合次数.append(0)
for u in range(100000):
    new = 洗牌(弃牌堆)
    for i in range(len(牌堆)):
        if 牌堆[i]==new[i]:
            重合次数[i] += 1
print(重合次数)
            

目前python主要使用的打乱列表(数组)的方法主要是这两种,
random.shuffle()
numpy.random.permutation()
经过上面代码的测试,分别有以下结果

#100000次调用shuffle方法
[667, 691, 627, 616, 612, 630, 646, 615, 630, 633, 611, 606, 677, 583, 647, 609, 633, 626, 628, 609, 603, 614, 598, 578, 608, 631, 604, 591, 616, 594, 631, 654, 630, 645, 606, 622, 678, 618, 609, 669, 633, 605, 627, 603, 621, 626, 646, 652, 670, 646, 669, 625, 573, 615, 639, 629, 617, 626, 625, 601, 649, 623, 618, 645, 657, 624, 676, 634, 598, 657, 642, 606, 642, 577, 602, 641, 642, 604, 607, 667, 594, 614, 639, 626, 671, 609, 597, 621, 610, 636, 613, 660, 604, 581, 622, 642, 634, 641, 641, 620, 649, 612, 575, 626, 619, 662, 591, 639, 602, 627, 642, 638, 611, 645, 622, 639, 680, 627, 665, 579, 595, 654, 598, 624, 618, 634, 611, 693, 650, 609, 635, 633, 587, 585, 644, 636, 663, 643, 620, 626, 651, 606, 610, 639, 640, 662, 567, 627, 602, 644, 585, 606, 670, 616, 653, 623, 606, 601, 590, 623]

#100000次调用permutation方法
[614, 636, 643, 638, 632, 586, 585, 628, 612, 589, 635, 643, 601, 634, 628, 597, 675, 589, 602, 653, 621, 613, 660, 602, 655, 553, 562, 579, 628, 630, 651, 646, 651, 580, 588, 630, 652, 636, 600, 629, 583, 579, 644, 650, 592, 615, 643, 617, 677, 631, 642, 628, 612, 628, 623, 620, 612, 603, 630, 655, 588, 610, 612, 635, 615, 638, 631, 636, 626, 681, 614, 626, 617, 638, 630, 650, 615, 609, 632, 574, 617, 585, 587, 601, 611, 613, 574, 618, 632, 632, 609, 608, 646, 609, 610, 626, 615, 629, 635, 655, 606, 616, 588, 639, 597, 605, 667, 612, 668, 618, 565, 610, 633, 617, 629, 643, 587, 577, 610, 606, 599, 627, 586, 602, 651, 624, 584, 627, 620, 608, 638, 614, 639, 630, 660, 627, 557, 641, 656, 621, 618, 650, 638, 659, 621, 661, 603, 646, 600, 604, 563, 607, 626, 582, 623, 627, 587, 672, 594, 638]

我本着学习的态度,查阅了shuffle方法的源代码

核心的代码就3行,其实就是非常经典的Fisher–Yates shuffle算法的实现,Fisher–Yates shuffle算法伪码如下:

– To shuffle an array a of n elements (indices 0…n-1):
for i from n−1 downto 1 do
j ← random integer such that 0 ≤ j ≤ i
exchange a[j] and a[i]   
第一步 即从0到N-1个元素中随机选择一个与第N-1个替换
第二步 从0到N-2个元素中随机选择一个与第N-2个替换

第k步 从0到N-k个元素中随机选择一个与第N-K个替换

我们先从第一步来看,
假设有4个元素
第1个元素被替换的概率是1/4
第2个元素被替换的概率是1/4
第3个元素被替换的概率是1/4
第4个元素被替换的概率是3/4
然后进行第二步,此时最后一位元素被固定,它对于每个元素都有1/4的概率
若第1个元素被替换:
[4,2,3,1]
第二次替换过程中
第1个元素被替换的概率是1/3
第2个元素被替换的概率是1/3
第3个元素被替换的概率是2/3
同理可知其他情况
所以第三位元素在第二次替换过程中,

对于第1个元素有1/4*0+3/4*1/3=1/4
对于第2个元素有1/4*0+3/4*1/3=1/4
对于第3个元素有1/4*0+3/4*1/3=1/4
对于第4个元素有1/4*1+3/4*0=1/4

易于理解 每个位置取到每个元素的概率都是均等的

最后还是要说一点
random.shuffle()和numpy.random.permutation()方法有一个小区别要注意
permutation的返回值是numpy.ndarray类型,不要把它当做列表类型了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值