假设给了您一个公平的硬币,并且您想模拟重复翻转一个公平的(六面)骰子的概率分布。我最初的想法是,我们需要选择适当的整数,使2 k = 6 m。所以翻转硬币后ķ倍,我们通过将范围映射由第k比特串长度到管芯的输出编码数[ 0 ,2 ķ - 1 ]每个的长度为6个的间隔米。但是,这是不可能的,因为2 k仅有两个素数,但2 k的素数包括3。应该有其他简单的方法来执行此操作,对吗?
假设给了您一个公平的硬币,并且您想模拟重复翻转一个公平的(六面)骰子的概率分布。我最初的想法是,我们需要选择适当的整数,使2 k = 6 m。所以翻转硬币后ķ倍,我们通过将范围映射由第k比特串长度到管芯的输出编码数[ 0 ,2 ķ - 1 ]每个的长度为6个的间隔米。但是,这是不可能的,因为2 k仅有两个素数,但2 k的素数包括3。应该有其他简单的方法来执行此操作,对吗?
Answers:
要拥有一种比@FrankW所指出的方法稍微有效的方法,但是使用相同的想法,您可以翻转硬币次以得到2 n以下的数字。然后将其解释为一批m次模子翻转,其中m是最大数目,因此6 m < 2 n(如前所述,在这里永远不存在相等性)。如果得到的数字大于或等于6 m,则必须拒绝该值并重复所有n次翻转。
您可以实现一个函数,该函数通过进行硬币翻转来返回单个骰子翻转,然后缓存以下m − 1个骰子翻转请求的结果。
有趣的是,某些值比其他值更好,因为它们的拒绝率较低。这是一个好值的列表(即拒绝率比前一个值低的值):
n m r
3 1 0.25
8 3 0.15625
13 5 0.05078125
44 17 0.0378308072686
75 29 0.0247036782182
106 41 0.0113974522704
243 94 0.00933096248381
380 147 0.00726015308463
517 200 0.00518501504347
654 253 0.00310553931213
791 306 0.00102171682348
与式获得: 。
第一行对应@FrankW的答案,拒绝率为25%。以下数字很不错:和n = 13都可以保存在单个整数静态变量中。特别是,n = 13的拒绝率仅为5%,相对于25%而言,这是一个明智的改进,这使其成为可能实施的良好选择。
您可以做的是采用一种称为拒绝采样的方法:
自每组中有 8种可能的结果导致终止,需要超过l组翻转才能获得掷骰的概率为(1−6。因此,该方法在实践中是有效的。
改进之处:
@Emanuele Paolini解释说,如果需要多个压模辊,如何减少重新轧辊的数量。
拒绝采样的替代方法(如FrankW的答案所述)是使用缩放算法,该算法将[7,8]的答案考虑在内,就好像是另一次硬币掷硬币一样。
mathforum.org上有一个非常详细的解释,其中包括算法(它NextBit()
会掷出您的硬币)。
用普通硬币投掷骰子的情况(采样2→6)比通用算法更容易。您只需将失败(7或8)作为另一个硬币输入,然后再进行两次翻转。
使用dM模拟dN滚动的另一种方法(在使用d2询问特定问题d6的情况下)是将间隔[0,1)划分为长度为N / [N,[0, 1 / N),[1 / N,2 / N),...,[(N-1)/ N,N)。
使用dM在[0,1)中生成基本M分数0.bbbb...。如果该值落在[(i-1)/ N,i / N)中,则将i作为dN的卷。请注意,您只需要生成分数的足够的基M位数即可确定分数所在的间隔。
我正在提供此解释,因为它可能有助于简化某些情况下对概率的理解或分析。
FrankW建议使用拒绝采样,将硬币翻转三遍,如果结果在正确的范围内,则保持结果;否则,重复三遍翻转,直到成功为止。
Ángel建议在每个试验中保存一次翻转,用之前三组中两个未使用的值剩余的二元选择代替它。
这实际上意味着在前三个翻转中产生了一点信息,而这并不需要产生。更准确地说,您应该只需要掷硬币两次就可以知道当前的掷骰是否成功。
知道当前的一组翻转是否成功是唯一重要的概率,因为解释一组成功的翻转与概率无关。这可以在该组的所有翻转完成之前知道。
这可以通过至少两种方式来实现,或更准确地说,通过翻转的两种不同的解释来实现。可能还有其他。
成对分组结果
想法是仅考虑由任意三个双翻转配置表示的三个值(1,2),(3,4)和(5,6),例如TT,TH,HT。然后,您可以使用两次翻转应用拒绝采样,每当获得故障配置HH时重复一次。
一旦获得了三种成功配置中的一种,就可以再次翻转硬币,以决定是否应该采用对应货币对的第一个或第二个值。
早期发现翻转失败
这个想法是对三重翻转配置使用略有不同的读数。如果将Head和Tail解释为1和0,则配置应对应于二进制解释加1。也就是说,TTT(即000)对应于1,HTH(即101)对应于6,HHT(即110)与HHH(即111)对应于7和8,或[1,6]以外的任何值。
然后我们知道翻转集仅在前两次翻转中是成功还是失败。如果它们产生HH,则翻转集将失败,而与最后一次翻转无关。因此可以跳过。
我认为总是可以将早期检测作为一种解释,但是根据模拟骰子上面孔的数量,可能会在无数次翻转之后进行故障检测。
例如,对于10个面子骰子,原则上您需要4组翻转的翻转集,其中6种配置对应于失败。诀窍是使所有故障配置都位于二进制值序列的高端,如下所示:
TTTT 0000 1
HTTT 1000 9
HTTH 1001 10
HTHT 1001 11
HTHH 1011 12
HHTT 1100 13
HHHH 1111 16
成功的配置对应于范围[1,10],失败的则对应于范围[11,16]。
然后,当前两个翻转给出HH或前三个翻转给出HTH时,您将失败,而不必尝试缺少该集合的翻转。
如果没有失败,则只需终止一组翻转即可。
有两种众所周知的方法。一种是“拒绝采样”。例如,使用三位从六个值中选择一个,然后再次尝试两个额外的样本。或使用14位(8192个值)从1到6中选择5个值(可能性为7776),在256种情况下,再尝试13种。
另一种方法是使用压缩/解压缩算法的解压缩部分:通过算术编码,可以压缩几乎没有冗余的从1到6的随机值序列。随机生成压缩序列,然后将其解压缩。这要复杂得多,但是实际上将不需要任何其他随机数。
如果解释多余,对不起。我不确定要涉及多少细节或该概念易于理解。
假设您有三个硬币(普通硬币)。如果您将增量值分配给每个硬币的每一面,则将有六个值。
像这样:在第一个硬币上,正面为1,在后面为2。在第二个硬币上,正面为3,在后面为4。在第三个硬币上,正面为5,在后面为6。
翻转硬币会留下一组三个数字,即当前的一组数字。现在,您的当前集合将成为您先前的集合,并且您将重复此过程以获取新的三个数字集合。
继续执行此操作,直到从您的当前号码到先前的号码中只有一个号码匹配。那是你的电话号码。
因此,如果您获得了当前集合的[头,尾,头],则为[1,4,5]。现在您再次翻转它们,当前设置为[2,4,5]。两场比赛。不好。再试一遍。您得到[2,3,6]。只有一场比赛。你的人数是两个。
任何给定的号码都会有相等的机会出现,但并不是特别划算,因为只有3/32的变化可以使任何给定的一组对成功(只有一场比赛)。因此,平均而言,该算法必须重复大约十次。而且,它不容易推广到奇数管芯。
至少,这可能是值得深思的。非常有趣的问题。
我将掷硬币三次,并将结果解释为二进制数,拒绝超出范围的结果。
例如,让heads为1,tails为0。如果将其翻转3次,得到head,tails和heads,则将具有二进制101,即十进制5。HHT = 110b =6。TTT= 000b = 0且HHH = 111b = 7,这两个值均超出范围,将被拒绝,您将需要取整所有数字。
不幸的是,一个人不能(忠实地)使用(一个或多个)公平硬币来模拟(公平)死亡。
但是,人们可以用一个公平的“三币”来做到这一点(如果可以使用这样的术语)。表示具有3个结果的硬币。还有一个简单的2枚硬币,因此这2枚硬币的联合空间与骰子的事件空间完全匹配。
拒绝采样(如某些答案中所述)确实可以提供近似的模拟。但是它仍然会存在一定数量的错误或概率不匹配(在有限时间内)。因此,如果要实际匹配这两个系统的事件空间,则在某些情况下它将无法正常工作。
在概率模拟中(以拒绝采样为例),生成的典型序列确实确实表现出相对的基本概率(在这种情况下,是模具的事件空间)。但是(如评论中所述),这些典型序列中的每一个都可以包含完全相同结果的任意长子序列。这意味着,为了使用拒绝采样(在某些情况下),它可能会花费很长时间,或者由于事件空间某些部分的过多表示或不足表示,生成的分布将有偏差(即不公平) 。如果不是这种情况,则可以使用确定性算法,该算法将与骰子和硬币的事件空间完全匹配(在维度上不匹配)。