调试:在Python/random中洗牌

2024-10-01 15:44:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道这个题目听起来很无聊,因为很多人已经问过这个话题了。我希望它能帮助我深入了解随机模块的工作原理。问题是,我写了两个不同的函数,我认为应该是相同的,但是我得到的结果却不一样,我不明白为什么。在

我希望以“洗牌良好”结束,我只关心牌是红色还是黑色,所以我的牌组非常简单。我叫“1”红色,“0”黑色。在

我的想法是通过附加一个1(红色)if来构建这个面板随机。随机()是>;.5,否则为0(黑色),当我达到一种颜色的26(一半)时,只会自动追加1或0。但是出了点问题。deckmaker()不能正常工作,尽管deckmaker2()可以。谁能提供见解?在

import random

def deckmaker():
    deck = []
    for i in range(52):
        if deck.count(0) == 26:
            deck.append(1)
        elif deck.count(1) == 26:
            deck.append(0)
        elif random.random() > .5:
            deck.append(0)
        else:
            deck.append(1)
    return deck

def deckmaker2():
    newdeck = []
    for i in range(26):
        newdeck.append(0)
    for i in range(26):
        newdeck.append(1)
    deck = []
    for i in range(52):
        x = random.randint(0,len(newdeck)-1)
        deck.append(newdeck.pop(x))
    return deck

注意:在写这个问题时,我发现随机洗牌list操作符,它和我的第二个函数做的是一样的事情,所以得到无序的牌堆当然很容易。但是我仍然想知道为什么我的原始代码没有做同样的事情。在

编辑:很抱歉对deckmaker()的确切问题含糊其辞。问题是,我不太明白怎么回事。它与这样一个事实有关,在它产生的牌堆上,当你一张一张地“翻转”牌时,有一些策略可以让你预测“下一张牌”是红色还是黑色,这与使用随机洗牌在

编辑2:[更多信息]我将解释我如何确定deckmaker不工作,以防这很重要。 我在写这个程序来模拟张贴在这里的谜题:http://www.thebigquestions.com/2013/12/17/tuesday-puzzle-4/

我的策略是记住最后几张牌,然后用这些信息来决定什么时候拿下一张牌。我想也许在连续拿到5张“黑”牌之后,现在是预测“红”的好时机。我是这样实现的:

^{pr2}$

结果我拿的牌中有一半以上是“红色”的,这是我在连续抽了5张红色牌后才拿牌的结果。这没有意义,所以我寻找了一种不同的方法来创建甲板,得到了一个更正常的结果。但我还是不知道我原来的甲板有什么问题。在


Tags: 函数inforifdefcountrangerandom
2条回答

一般来说,除非你能严格证明随机化方法是正确的,否则你不应该相信它是正确的。这通常很难。在

为了深入了解您的问题,让我们概括一下有问题的函数:

import random

def deckmaker(n):
    half = n // 2
    deck = []
    for i in range(n):
        if deck.count(0) == half:
            deck.append(1)
        elif deck.count(1) == half:
            deck.append(0)
        elif random.random() > .5:
            deck.append(0)
        else:
            deck.append(1)
    return deck

下面是一个小司机:

^{pr2}$

运行它:

(0, 1) 495
(1, 0) 505

两种可能性差不多。很好!现在尝试一副4号的牌;只需将相关行改为:

c[tuple(deckmaker(4))] += 1

运行它:

(0, 0, 1, 1) 236
(0, 1, 0, 1) 127
(0, 1, 1, 0) 133
(1, 0, 0, 1) 135
(1, 0, 1, 0) 130
(1, 1, 0, 0) 239

哎呀!如果你愿意的话,你可以进行一个正式的卡方检验,但是很明显,两个排列(第一个和最后一个)的概率是另外四个的两倍。因此,输出甚至不接近随机性。在

为什么?想想看;-)

提示

对于大小为2*M的一组,第一个M项都是0的几率有多大?对此有两个答案:

  1. 如果M零和M的所有排列都有相同的可能性,则概率是(2*M)-choose-M中的1(选择M零位置的方法的数目)。

  2. 在函数构造一个deck的方式中,2**M中的概率是1(在第一个M位置中,0和1的可能性相等)。

一般来说,(2*M)-choose-M2**M大得多,因此函数构造一个从所有零开始的牌堆的次数远远超过“它应该”的次数。对于一副52张牌(M == 26):

>>> from math import factorial as f
>>> one = f(52) // f(26)**2
>>> two = 2**26
>>> float(one) / two
7389761.998476148

所以“从26个零开始”的可能性比应该的高出700万倍。酷:-)

一次一个“

那么,是否有可能一次正确地选择一个0或1?是的!你只需要使用正确的概率:当还有nzero个零来选择,还有nremaining总共还有nremaining的“牌”需要被选择,那么选择0的概率是nzero / nremaining

def deckmaker(n=52):
    deck = [None] * n
    nremaining = float(n)
    nzero = nremaining / 2.0
    for i in range(n):
        if random.random() < nzero / nremaining:
            deck[i] = 0
            nzero -= 1.0
        else:
            deck[i] = 1
        nremaining -= 1.0
    return deck

请注意,不需要计数。当nzero变为0.0时,if测试将永远不会成功(random() < 0.0不会发生);一旦我们选择了n/2个,则{}将为真,if测试将始终成功(random() < 1.0始终为true)。很可爱;-)

我不确定这是什么意思,但我认为第一种方法生成的最后一张牌极有可能是相同的。在

在50个或更少的样本中得到26个1或26个0的可能性似乎很大(我认为可以使用交换二项分布来计算)。即使是一个很小的机会也意味着你应该赌最后一张牌是相同的(因此其他牌是相反的)颜色。在

你可以做的就是把0和1加起来,直到有52张牌,然后在最后把随机的1变成0(或者反过来),直到每一张都有26张。在

编辑: 假设一副牌有4张牌。前两种颜色是随机的:

25% (0, 0)
25% (0, 1)
25% (1, 0)
25% (1, 1)

但是对于(0, 0)和{},最后两张牌已经确定,将分别是(1, 1)和{}。其他人还需要一个数字来确定结果:

^{pr2}$

所以正如你所见,并非所有的选择都是一样的。当然,52张牌的差别较小,但想法是一样的。在

相关问题 更多 >

    热门问题