代码之家  ›  专栏  ›  技术社区  ›  Henrik

使用python random.shuffle进行无序播放的列表的最大长度?

  •  32
  • Henrik  · 技术社区  · 14 年前

    我有一个列表,我用python内置的shuffle函数对其进行shuffle处理( random.shuffle )

    但是,python引用声明:

    注意,即使很小 len(x) ,x的置换总数大于大多数随机数生成器的周期;这意味着绝大多数长序列的置换永远无法生成。

    现在,我想知道这个“相当小的len(x)”是什么意思。100,1000,10000,…

    3 回复  |  直到 7 年前
        1
  •  61
  •   Henrik    11 年前

    tl;dr:它以2080个元素“打破”列表,但不要担心太多:)

    完整答案:

    首先,请注意,“洗牌”列表可以理解为(概念上)生成列表元素的所有可能排列,并随机选择其中一个排列。

    那么,您必须记住,所有独立的计算机化随机数生成器实际上都是“伪”随机数。也就是说,它们实际上不是随机的,而是依靠一系列的因素来尝试生成一个在高级或有目的地复制时很难猜测的数字。在这些因素中,通常是先前生成的数字。因此,在实践中,如果您连续使用一个随机生成器若干次,最终将再次开始获得相同的序列(这是文档所指的“周期”)。

    最后,lib/random.py(随机模块)上的docstring指出“随机数生成器的周期是 2**19937-1 ."

    所以,考虑到所有这些,如果你的清单 2**19937 或者更多的排列,其中一些永远不会通过改变列表获得。您将(在概念上)生成列表的所有排列,然后生成一个随机数x,并选择xth排列。下一次,生成另一个随机数y,并选择yth排列。等等。但是,因为有比随机数更多的排列(因为,最多在 2×*1973-1 生成的数字,您将再次得到相同的数字),您将再次开始选择相同的排列。

    所以,你看,这并不完全取决于你的列表有多长(尽管它确实进入了等式)。也, 2×*1973-1 是一个很长的数字。但是,尽管如此,根据你洗牌的需要,你应该记住所有这些。在简单的情况下(并且快速计算),对于没有重复元素的列表,2081个元素将产生 2081! 排列,这比 2×19937 .

        2
  •  19
  •   Tim Peters    11 年前

    我最初在python源代码中写了这个评论,所以也许我可以澄清一下;-)

    当评论被引入时,python的wichmann-hill generator的周期要短得多,我们甚至无法生成一副牌的所有排列。

    现在的周期是天文上的大,2080是正确的当前上限。医生们可以加强对这方面的了解,但他们会变得非常乏味。

    有一个非常简单的解释:周期p的prng有p可能的起始状态。起始状态完全决定了产生的排列。因此,周期p的prng不能产生超过p的不同排列(这是一个绝对上限——可能无法实现)。这就是为什么比较n!p是这里的正确计算。事实上:

    >>> math.factorial(2080) > 2**19937 - 1
    False
    >>> math.factorial(2081) > 2**19937 - 1
    True
    
        3
  •  4
  •   Peter Mortensen TravisEz13    7 年前

    它们的意思是n个对象上的排列(注意n!)长得很快,高得出奇。

    基本上是N!=N x N-1 x…x 1;例如,5!=5 x 4 x 3 x 2 x 1=120,这意味着有120种可能的方法可以改变5项列表。

    在同一个python页面文档中,它们给出了2^19937-1作为句点,即4.something_10^6001或其他值。基于维基百科的因子分析页面,我想是2000年吧!应该在那附近。(对不起,我找不到确切的数字。)

    所以基本上洗牌会有很多可能的排列,所以可能没有真正的理由去担心那些它不会的排列。

    但如果这真的是一个问题(烦人的客户可能要求保证随机性?),您还可以将任务卸载到某个第三方;请参见 http://www.random.org/ 例如。