脑筋急转弯:如何使用具有pr(head)= p的偏向硬币以相等的概率生成7个整数?


58

这是我在Glassdoor上发现的一个问题:如何使用具有的硬币以相等的概率生成7个整数Pr(Head)=p(0,1)

基本上,您有一个硬币,可能是公平的,也可能是不公平的,这是唯一的随机数生成过程,因此想出一个随机数生成器,它输出从1到7的整数,其中获得每个整数的概率是1/7。

数据生成过程的效率至关重要。



12
有无数种方法可以做到这一点。这个问题的一个更有趣的版本在某种明确的意义上要求最好的方法。最好的自然感觉是每个整数生成的翻转次数最少。另一个有趣的版本是描述所有可能的解决方案(依赖于硬币的独立翻转而已)。
ub

1
@whuber很好的建议,我已经编辑了问题以反映您的评论。
亚马逊

<<<基本上,您有一个硬币可能是公平的,也可能是不公平的,这是唯一的随机数生成过程>>>这是否意味着以不同于翻转硬币和检查头的任何其他方式使用硬币vs. tail是“禁止的”,因为这将是另一个随机数生成过程?
TinglTanglBob

9
硬币的年度Mod 7。
纳特

Answers:


56

翻转硬币两次。如果它降落HHTT,请忽略它,然后再次翻转两次。

现在,硬币有相等的概率出现HTTH。如果出现HT,叫这个H1。如果出现TH,叫这个T1

继续获取H1T1直到连续获取三个。这三个结果为您提供了基于下表的数字:

H1 H1 H1 -> 1
H1 H1 T1 -> 2
H1 T1 H1 -> 3
H1 T1 T1 -> 4
T1 H1 H1 -> 5
T1 H1 T1 -> 6
T1 T1 H1 -> 7
T1 T1 T1 -> [Throw out all results so far and repeat]

我认为这可以很好地工作,尽管您会在过程中浪费很多!


4
唯一的限制是正面的概率为“ p”。请注意,p可以为或。因此,这不能保证能正常工作,但即使在那种情况下,Sycorax(或Sephan)也能工作。101
gung-恢复莫妮卡

8
@gung:我不确定我会为一个带有两个头或两个尾巴的硬币工作。
S. Kolassa-恢复莫妮卡

6
可能性为,它将在有限时间内完成。1
clark

18
这称为冯诺依曼美白。
DonFusili

4
您可以迭代von Neumann提取器,以更充分地从序列中提取熵。收集所有的HH和TT对,认为这是一个序列,运用冯·诺依曼提取到,等
西蒙斯

47

假设。p(0,1)

步骤1 :。抛硬币5次。

如果结果是

1(H,H,H,T,T),返回并停止。1

2(H,H,T,T,H),返回并停止。2

3(H,T,T,H,H),返回并停止。3

4(T,T,H,H,H)返回并停止。4

5(T,H,H,H,T),返回并停止。5

6(H,H,T,H,T),返回并停止。6

7(H,T,H,T,H),返回并停止。7

第2步:。如果结果不是以上任何一项,请重复步骤1。

请注意,无论的值如何,上面列出的七个结果中的每一个都有的概率,并且预期抛硬币的数量为。抛掷器不需要知道的值(和除外);可以保证实验终止时,这七个整数同样有可能被返回(并保证以结束)。q = p 31 - p 2 5p(0,1)q=p3(1p)2 pp0p1157qpp0p11


6
我们是否可以通过允许此处指定的序列或每次翻转的序列来减少预期的抛掷次数。例如:对于1,(H,H,H,T,T)或(T,T,T,H,H)?
moreON

5
您也可以添加补码。如果结果是(H,H,H,T,T)或(T,T,T,H,H),则返回1并停止,依此类推。在这种情况下,每个结果的概率为。q=p3(1p)2+p2(1p)3
Sextus Empiricus

2
如果结果不具有任何(H,H,H,T,T)排列,是否仅可以添加另一个硬币翻转?使用额外的投掷硬币,您将需要(H,H,H,T,T,T)和(H,H,T,T,T,T)的另一个映射以及每个xT(7-x)H组合可以按7个或更多不同的顺序排列(从1到7)。与其重新投入5个硬币,不如将其扔掉另外1次,但我不确定它是否起作用:D
TinglTanglBob

5
即时翻动硬币7次可能是最好的选择,因为比保证的时间要大,您会从中得到一个随机数(因此,唯一的例外是硬币正面朝上或尾随了全部7次尝试) 。因此,经过7次抛掷,您最终可能会获得1个最多6个头(我将0和7选项排除在外,因为它毫无意义)。如果一个头有(H,T,T,T,T,T,T)的7种不同排列; 如果2领先21;如果3超过35,如果4 35头; 如果5 21头; 如果6 7头; 每个都可以完美地映射到1-7,而不会丢失任何组合。
TinglTanglBob

2
@TinglTanglBob这基本上是Martijn Weterings的答案;-)
M.Herzkamp

22

概括Dilip Sarwate描述的情况

其他答案中描述的某些方法使用的是您抛出序列的方案n在“转弯”中硬币并根据结果选择1或7之间的数字或放弃转弯并再次投掷。

诀窍是在可能性的扩展中找到7个结果的倍数,它们具有相同的概率pk(1p)nk并使它们彼此匹配。

因为结果总数不是7的倍数,所以我们有一些我们无法分配给结果的结果,并且有一定的概率需要丢弃结果并重新开始。


每转使用7次掷硬币的情况

直觉上我们可以说掷骰子七次会非常有趣。因为我们只需要把中的扔掉27可能性。即7次正面和0次正面。

对于所有其他可能性,总有7个盒数相同的磁头。即1头7例,2头21例,3头35例,4头35例,5头21例,6头7例。272

因此,如果您计算数字(丢弃0个头和7个头)

X=k=17(k1)Ck

如果使用 Bernoulli分布变量(值0或1),则X模7是一个具有七个可能结果的统一变量。Ck


比较每转硬币翻转的次数

问题仍然是每转的最佳滚动数是多少。每转掷更多骰子会花费更多,但会降低不得不再次掷骰的可能性。

下图显示了手动计算每转硬币前几次翻转的次数。(可能有一种分析解决方案,但是我可以肯定地说,具有7个硬币翻转的系统提供了关于必要数量硬币翻转的期望值的最佳方法)

预期的硬币翻转次数

# plot an empty canvas
plot(-100,-100,
     xlab="flips per turn",
     ylab="E(total flips)",
     ylim=c(7,400),xlim=c(0,20),log="y")
title("expectation value for total number of coin flips
(number of turns times flips per turn)")

# loop 1
# different values p from fair to very unfair 
# since this is symmetric only from 0 to 0.5 is necessary 

# loop 2
# different values for number of flips per turn
# we can only use a multiple of 7 to assign 
#   so the modulus will have to be discarded
#   from this we can calculate the probability that the turn succeeds
#   the expected number of flips is 
#       the flips per turn 
#             divided by 
#       the probability for the turn to succeed 

for (p in c(0.5,0.2,0.1,0.05)) {
  Ecoins <- rep(0,16)
  for (dr in (5:20)){
    Pdiscards = 0
    for (i in c(0:dr)) { 
      Pdiscards = Pdiscards + p^(i)*(1-p)^(dr-i) * (choose(dr,i) %% 7)
    }
    Ecoins[dr-4] = dr/(1-Pdiscards)
  }
  lines(5:20, Ecoins)
  points(5:20, Ecoins, pch=21, col="black", bg="white", cex=0.5)
  text(5, Ecoins[1], paste0("p = ",p), pos=2)
}

使用提前停止规则

注意:以下计算是针对翻转次数的期望值,对于公平的硬币,对于不同的做到这一点将变得一团糟,但是原理仍然相同(尽管不同的簿记方式案件是必要的)p=0.5p

我们应该可以选择情况(而不是的公式),以便我们可以更早停止。X

  • 通过五次硬币翻转,我们可以得到六种可能的不同的无序的首尾集:

    1 + 5 + 10 + 10 + 5 + 1有序集

    我们可以使用十种情况的组(即具有2个头的组或具有2个尾部的组)来选择(等概率)一个数字。在2 ^ 5 = 32例中有14例发生这种情况。这给我们留下了:

    1 + 5 + 3 + 3 + 5 + 1有序集

  • 额外掷出(第6)我们可以得到七种可能的无序的组:

    1 + 6 + 8 + 6 + 8 + 6 + 1有序集

    我们可以使用八种情况的组(即具有3个头的组或具有3个尾部的组)来选择(等概率)一个数字。2 *(2 ^ 5-14)= 36例中有14例发生这种情况。这给我们留下了:

    1 + 6 + 1 + 6 + 1 + 6 + 1有序集

  • 通过另一次(第7次)额外的硬币翻转,我们可以得到八种可能的无序的正面和反面组:

    1 + 7 + 7 + 7 + 7 + 7 + 7 + 1有序集

    我们可以使用具有七个案例(所有尾巴和所有头案例除外)的组来选择(均等概率)一个数字。在44例病例中有42例发生这种情况。这给我们留下了:

    1 + 0 + 0 + 0 + 0 + 0 + 0 + 1有序集

    (我们可以继续执行此操作,但只有在第49步中才能使我们受益)

所以选择一个数字的可能性

  • 每5次翻转是1432=716
  • 每6次翻转为9161436=732
  • 每7次翻转是11324244=231704
  • 不是7次翻转是1716732231704=227

这使一轮翻转次数的期望值为条件,条件是成功且p = 0.5:

5716+6732+7231704=5.796875

在p = 0.5的条件下,翻转总数的期望值(直到成功):

(5716+6732+7231704)27272=539=5.88889


NcAdams的答案使用了该停止规则策略的一种变体(每次都提供两个新的硬币翻转),但并不是最佳地选择所有翻转。

Clid的答案也可能相似,尽管可能会有不规则的选择规则,即每两个硬币翻转可能会选择一个数字,但不一定具有相等的概率(差异会在以后的硬币翻转中得到修复)


与其他方法的比较

使用类似原理的其他方法是NcAdams和AdamO的方法。

原理是:在确定一定数量的首尾之后,才决定1到7之间的数字。在翻过次后,对于得出每个决策,都有一个类似的,同样可能的决策导致(相同的前额和尾数,但顺序不同)。某些前后关系可能导致重新开始的决定。xij

对于这种类型的方法,此处放置的方法是最有效的,因为它会尽早做出决定(一旦有第7个相等的概率的前后序列,在第翻转后,我们可以使用他们决定一个数字,如果遇到其中一种情况,我们就无需进一步处理了)。x

下面的图像和仿真对此进行了演示:

比较

#### mathematical part #####
set.seed(1)


#plotting this method
p <- seq(0.001,0.999,0.001)
tot <- (5*7*(p^2*(1-p)^3+p^3*(1-p)^2)+
       6*7*(p^2*(1-p)^4+p^4*(1-p)^2)+
       7*7*(p^1*(1-p)^6+p^2*(1-p)^5+p^3*(1-p)^4+p^4*(1-p)^3+p^5*(1-p)^2+p^6*(1-p)^1)+
        7*1*(0+p^7+(1-p)^7) )/
             (1-p^7-(1-p)^7)
plot(p,tot,type="l",log="y",
     xlab="p",
     ylab="expactation value number of flips"
     )

#plotting method by AdamO
tot <- (7*(p^20-20*p^19+189*p^18-1121*p^17+4674*p^16-14536*p^15+34900*p^14-66014*p^13+99426*p^12-119573*p^11+114257*p^10-85514*p^9+48750*p^8-20100*p^7+5400*p^6-720*p^5)+6*
          (-7*p^21+140*p^20-1323*p^19+7847*p^18-32718*p^17+101752*p^16-244307*p^15+462196*p^14-696612*p^13+839468*p^12-806260*p^11+610617*p^10-357343*p^9+156100*p^8-47950*p^7+9240*p^6-840*p^5)+5*
          (21*p^22-420*p^21+3969*p^20-23541*p^19+98154*p^18-305277*p^17+733257*p^16-1389066*p^15+2100987*p^14-2552529*p^13+2493624*p^12-1952475*p^11+1215900*p^10-594216*p^9+222600*p^8-61068*p^7+11088*p^6-1008*p^5)+4*(-
          35*p^23+700*p^22-6615*p^21+39235*p^20-163625*p^19+509425*p^18-1227345*p^17+2341955*p^16-3595725*p^15+4493195*p^14-4609675*p^13+3907820*p^12-2745610*p^11+1592640*p^10-750855*p^9+278250*p^8-76335*p^7+13860*p^6-
          1260*p^5)+3*(35*p^24-700*p^23+6615*p^22-39270*p^21+164325*p^20-515935*p^19+1264725*p^18-2490320*p^17+4027555*p^16-5447470*p^15+6245645*p^14-6113275*p^13+5102720*p^12-3597370*p^11+2105880*p^10-999180*p^9+371000
           *p^8-101780*p^7+18480*p^6-1680*p^5)+2*(-21*p^25+420*p^24-3990*p^23+24024*p^22-103362*p^21+340221*p^20-896679*p^19+1954827*p^18-3604755*p^17+5695179*p^16-7742301*p^15+9038379*p^14-9009357*p^13+7608720*p^12-
           5390385*p^11+3158820*p^10-1498770*p^9+556500*p^8-152670*p^7+27720*p^6-2520*p^5))/(7*p^27-147*p^26+1505*p^25-10073*p^24+49777*p^23-193781*p^22+616532*p^21-1636082*p^20+3660762*p^19-6946380*p^18+11213888*p^17-
           15426950*p^16+18087244*p^15-18037012*p^14+15224160*p^13-10781610*p^12+6317640*p^11-2997540*p^10+1113000*p^9-305340*p^8+55440*p^7-5040*p^6)
lines(p,tot,col=2,lty=2)

#plotting method by NcAdam
lines(p,3*8/7/(p*(1-p)),col=3,lty=2)

legend(0.2,500,
       c("this method calculation","AdamO","NcAdams","this method simulation"),
       lty=c(1,2,2,0),pch=c(NA,NA,NA,1),col=c(1,2,3,1))


##### simulation part ######

#creating decision table
mat<-matrix(as.numeric(intToBits(c(0:(2^5-1)))),2^5,byrow=1)[,c(1:12)]
colnames(mat) <- c("b1","b2","b3","b4","b5","b6","b7","sum5","sum6","sum7","decision","exit")

# first 5 rolls
mat[,8] <- sapply(c(1:2^5), FUN = function(x) {sum(mat[x,1:5])})

mat[which((mat[,8]==2)&(mat[,11]==0))[1:7],12] = rep(5,7) # we can stop for 7 cases with 2 heads
mat[which((mat[,8]==2)&(mat[,11]==0))[1:7],11] = c(1:7)   
mat[which((mat[,8]==3)&(mat[,11]==0))[1:7],12] = rep(5,7) # we can stop for 7 cases with 3 heads
mat[which((mat[,8]==3)&(mat[,11]==0))[1:7],11] = c(1:7)    

# extra 6th roll
mat <- rbind(mat,mat)
mat[c(33:64),6] <- rep(1,32)
mat[,9] <- sapply(c(1:2^6), FUN = function(x) {sum(mat[x,1:6])})

mat[which((mat[,9]==2)&(mat[,11]==0))[1:7],12] = rep(6,7) # we can stop for 7 cases with 2 heads
mat[which((mat[,9]==2)&(mat[,11]==0))[1:7],11] = c(1:7)   
mat[which((mat[,9]==4)&(mat[,11]==0))[1:7],12] = rep(6,7) # we can stop for 7 cases with 4 heads
mat[which((mat[,9]==4)&(mat[,11]==0))[1:7],11] = c(1:7)    

# extra 7th roll
mat <- rbind(mat,mat)
mat[c(65:128),7] <- rep(1,64)
mat[,10] <- sapply(c(1:2^7), FUN = function(x) {sum(mat[x,1:7])})

for (i in 1:6) {
  mat[which((mat[,10]==i)&(mat[,11]==0))[1:7],12] = rep(7,7) # we can stop for 7 cases with i heads
  mat[which((mat[,10]==i)&(mat[,11]==0))[1:7],11] = c(1:7)   
}


mat[1,12] = 7           # when we did not have succes we still need to count the 7 coin tosses
mat[2^7,12] = 7


draws = rep(0,100)
num = rep(0,100)
# plotting simulation
for (p in seq(0.05,0.95,0.05)) {
  n <- rep(0,1000)
  for (i in 1:1000) {
    coinflips <- rbinom(7,1,p)  # draw seven numbers
    I <- mat[,1:7]-matrix(rep(coinflips,2^7),2^7,byrow=1) == rep(0,7)                      # compare with the table
    Imatch = I[,1]*I[,2]*I[,3]*I[,4]*I[,5]*I[,6]*I[,7]        # compare with the table 
      draws[i] <- mat[which(Imatch==1),11]                 # result which number
      num[i]   <- mat[which(Imatch==1),12]                 # result how long it took
  }
  Nturn <- mean(num)                   #how many flips we made
  Sturn <- (1000-sum(draws==0))/1000   #how many numbers we got (relatively)
  points(p,Nturn/Sturn)
}

为了更好的比较,用缩放的另一个图像:p(1p)

与比例期望值的比较

放大本文和评论中描述的比较方法

这里介绍的比较方法

“第7步有条件跳过”是可以在早期停止规则上进行的轻微改进。在这种情况下,在第6次翻转之后,您不会选择概率相同的组。您有6个具有相等概率的组,而1个具有稍微不同的概率的组(对于最后一组,当您有6个正面或反面时,您需要再翻转一次额外的时间,并且由于您丢弃了7个正面或7个反面,您将结束毕竟具有相同的概率)


StackExchangeStrike撰写


我刚开始要对n = 7的情况进行计算,因为我觉得它可能比n = 1好。先生,请投票!
M.Herzkamp '18年

@ M.Herzkamp仍然可以进行一些小的改进。的计算不需要一个数字(一次掷硬币),因为它的系数为0。这个数字仅是确定全部为头或全部为尾的情况的必要条件,当我们已经知道我们可以将其省略有混合的情况。CkX
Sextus Empiricus

因此,改进后的硬币翻转次数减少了6次以上,作为所需硬币翻转次数的期望值。证明这是最佳解决方案的方法可能有所不同。克利德(Clid)创建的方案略有不同,允许在特定数量的硬币翻转中选择一个数字,但概率相等(至少不是针对该特定步骤,稍后将进行更正)。
Sextus Empiricus

但是,如果您要根据前五个结果决定是否掷出第六枚硬币,那么根据您获得的六次掷骰的条件,每组的概率是否与其他掷出的概率相同?
17:56累积

@累积您可以将其绘制为具有7个级别的二叉树。如果只有7个概率相等,我们将仅在节点之间进行选择。就像您早些砍了一些分支(在5或6级)。如果愿意的话,您可以继续执行直到第7步,而不是更早,但是对于这些特殊情况,第6和第7硬币翻转没有什么不同。
Sextus Empiricus

20

将一个框划分为七个等面积区域,每个区域均用整数标记。将硬币投掷到盒子中的方式使其在每个区域具有相等的着陆概率。

这只是开玩笑的一半-基本上与使用物理蒙特卡洛过程估算过程相同,例如将米粒滴到纸上并画上一个圆圈。π

这是在或的情况下唯一可行的答案之一。p = 0p=1p=0


2
您能建议一种将盒子分成七个等面积区域的方法,以最大程度地减少翻转,弹跳墙壁等造成的偏差吗?七个扇形角为360/7?
smci

1
@smci这就是为什么我规定您必须扔硬币,以便在每个正方形上都有统一的概率降落。如果从墙壁弹起会影响该概率,那么您必须在掷球时予以考虑。
恢复莫妮卡

17
是的,我知道这一点,我是在向指出,只是说“无偏向地扔”而没有确切定义如何实现它,并不是真正的完整答案……在这种情况下,翻转H / T基于方法是优越的。
smci

1
在实践中可能很难建立“相等的区域,并且每个区域的投掷概率均等”。在实践中,可能更容易划出大量的“练习”,然后根据经验将着陆区域细分为等概率的空间(例如,掷700次,划出一条线,切断最远的100次,然后再进行下一次100等)。生成一个随机位的简化方法是将硬币投掷两次-如果第一次掷得更远,则为0,如果第二次掷得更远,则为1
Silverfish '18

4
@TheScienceBoy有一个很好的答案,可悲的是,它删除了一个有趣的替代方法-有效地,使用硬币作为旋转器,并沿圆周标记7个部分-保留了该答案的大部分精神,但实际上可能更直接进行!
Silverfish '18年

8

编辑:基于其他人的反馈。

这是一个有趣的想法:

设置{1,2,3,4,5,6,7}的列表。依次为列表中的每个元素投掷硬币。如果将其正面朝上放到特定元素上,请从列表中删除该数字。如果删除了列表的特定迭代中的所有数字,请重复采样。这样做直到只剩下一个数字。

drop.one <- function(x, p) {
  drop <- runif(length(x)) < p
  if (all(drop))
    return(x)
  return(x[!drop])
}

sample.recur <- function(x, p) {
  if (length(x) > 1)
    return(sample.recur(drop.one(x, p), p))
  return(x)
}

# x <- c(1:7,7:1)
x <- 1:7
p <- 0.01

out <- replicate(1e5, sample.recur(x, p))

round(prop.table(table(out)), 2)

给我大致均匀的分布

> round(prop.table(table(out)), 2)
out
   1    2    3    4    5    6    7 
0.14 0.14 0.15 0.14 0.14 0.14 0.14 

N


硬币投掷次数的期望值评估

xy

M=[q700000117p1q6q600000021p2q56p1q5q50000035p3q415p2q45q4q4000035p4q320p3q310p2q34p1q3q300021p5q215p4q210p3q26p2q23p1q2q2007p6q16p5q15p4q14p3q13p2q12p1q100p7p6p5p4p3p200]

(MI)v=0

E(n)=247p(1p)

掷硬币的期望值比较

p>2/3

wxMaxima找到的解决方案

M: matrix(
 [(1-p)^7,        0,          0,0,0,0,1,1], 
 [7* p*(1-p)^6,   (1-p)^6,        0,0,0,0,0,0], 
 [21*p^2*(1-p)^5, 6*p*(1-p)^5,    (1-p)^5,0,0,0,0,0], 
 [35*p^3*(1-p)^4, 15*p^2*(1-p)^4, 5*p*(1-p)^4,(1-p)^4,0,0,0,0], 
 [35*p^4*(1-p)^3, 20*p^3*(1-p)^3, 10*p^2*(1-p)^3,4*p*(1-p)^3,(1-p)^3,0,0,0], 
 [21*p^5*(1-p)^2, 15*p^4*(1-p)^2, 10*p^3*(1-p)^2,6*p^2*(1-p)^2,3*p*(1-p)^2,(1-p)^2,0,0], 
 [7* p^6*(1-p)^1, 6*p^5*(1-p),    5*p^4*(1-p),4*p^3*(1-p),3*p^2*(1-p),2*(1-p)*p,0,0], 
 [p^7,        p^6,        p^5,p^4,p^3,p^2,0,0]
);
z: nullspace(M-diagmatrix(8,1));
x : apply (addcol, args (z));
t : [7,6,5,4,3,2,0,0];
plot2d(t.x/x[7],[p,0,1],logy);

R中的计算

# plotting empty canvas
plot(-100,-100,
     xlab="p",
     ylab="E(total flips)",
     ylim=c(10,1000),xlim=c(0,1),log="y")

# plotting simulation
for (p in seq(0.1,0.9,0.05)) {

  n <- rep(0,10000)
  for (i in 1:10000) {
    success  = 0
    tests = c(1,1,1,1,1,1,1)     # start with seven numbers in the set
    count = 0
    while(success==0) {
      for (j in 1:7)  {
        if (tests[j]==1) {
          count = count + 1
          if  (rbinom(1,1,p) == 1) {
            tests[j] <- 0        # elliminate number when we draw heads
          }
        }
      }
      if (sum(tests)==1) {
        n[i] = count
        success = 1              # end     when 1 is left over
      }
      if (sum(tests)==0) {
        tests = c(1,1,1,1,1,1,1) # restart when 0 are left over
      }
    }
  }
  points(p,mean(n))
}

# plotting formula
p <- seq(0.001,0.999,0.001)

tot <- (7*(p^20-20*p^19+189*p^18-1121*p^17+4674*p^16-14536*p^15+34900*p^14-66014*p^13+99426*p^12-119573*p^11+114257*p^10-85514*p^9+48750*p^8-20100*p^7+5400*p^6-720*p^5)+6*
    (-7*p^21+140*p^20-1323*p^19+7847*p^18-32718*p^17+101752*p^16-244307*p^15+462196*p^14-696612*p^13+839468*p^12-806260*p^11+610617*p^10-357343*p^9+156100*p^8-47950*p^7+9240*p^6-840*p^5)+5*
    (21*p^22-420*p^21+3969*p^20-23541*p^19+98154*p^18-305277*p^17+733257*p^16-1389066*p^15+2100987*p^14-2552529*p^13+2493624*p^12-1952475*p^11+1215900*p^10-594216*p^9+222600*p^8-61068*p^7+11088*p^6-1008*p^5)+4*(-
    35*p^23+700*p^22-6615*p^21+39235*p^20-163625*p^19+509425*p^18-1227345*p^17+2341955*p^16-3595725*p^15+4493195*p^14-4609675*p^13+3907820*p^12-2745610*p^11+1592640*p^10-750855*p^9+278250*p^8-76335*p^7+13860*p^6-
    1260*p^5)+3*(35*p^24-700*p^23+6615*p^22-39270*p^21+164325*p^20-515935*p^19+1264725*p^18-2490320*p^17+4027555*p^16-5447470*p^15+6245645*p^14-6113275*p^13+5102720*p^12-3597370*p^11+2105880*p^10-999180*p^9+371000
   *p^8-101780*p^7+18480*p^6-1680*p^5)+2*(-21*p^25+420*p^24-3990*p^23+24024*p^22-103362*p^21+340221*p^20-896679*p^19+1954827*p^18-3604755*p^17+5695179*p^16-7742301*p^15+9038379*p^14-9009357*p^13+7608720*p^12-
 5390385*p^11+3158820*p^10-1498770*p^9+556500*p^8-152670*p^7+27720*p^6-2520*p^5))/(7*p^27-147*p^26+1505*p^25-10073*p^24+49777*p^23-193781*p^22+616532*p^21-1636082*p^20+3660762*p^19-6946380*p^18+11213888*p^17-
  15426950*p^16+18087244*p^15-18037012*p^14+15224160*p^13-10781610*p^12+6317640*p^11-2997540*p^10+1113000*p^9-305340*p^8+55440*p^7-5040*p^6)
lines(p,tot)

#plotting comparison with alternative method
lines(p,3*8/7/(p*(1-p)),lty=2)

legend(0.2,500,
       c("simulation","calculation","comparison"),
       lty=c(0,1,2),pch=c(1,NA,NA))

1
聪明的主意(+1)。直观上讲,它应该起作用,因为对称性似乎可以消除对任何特定数字的偏见。不过,我还是很想看看证明。
恢复莫妮卡

6
这个想法确实很好,但是我有很高的概率(淘汰这个数字),我认为该行中的最后一个数字最有机会“生存”,因为所有其他前面的数字很可能在运行1之前就被踢出了?也许可以通过不按顺序扔硬币而是对x中的所有数字平行扔硬币来更改它?我猜该脚本的运行时间可能会增加:)
TinglTanglBob

2
我同意@TinglTanglBob-设置时,p <- 0.99我会得到输出0.89 0.02 0.02 0.02 0.02 0.02 0.02
Silverfish

6
不能在“回合”中执行消除操作来解决偏差问题吗?以7个数字开头。将剩下的每个数字投掷硬币,并消除掷出硬币的硬币。如果在一轮中消除了所有剩余的数字,请刮擦该轮的结果,然后重试。我不知道如何证明这一点,但是从直觉上讲,数字的顺序对于它们是否是“赢家”不再重要
Phil

1
p=0.01

5

问题有点模棱两可,是问“以相等的概率生成等于或小于7的随机整数”,还是问“以相等的概率生成7个等于或小于7的随机整数?” -但是整数的空间是多少?!?

我假设是前者,但是一旦解决了这个问题,我正在应用的相同逻辑也可以扩展到后者。

使用有偏向的硬币,您可以按照以下步骤生产公平的硬币:https : //en.wikipedia.org/wiki/Fair_coin#Fair_results_from_a_biased_coin

可以将7或更少的数字写成三位{0,1}数字。因此,所有需要做的就是按照上述步骤进行三遍,并将生成的二进制数转换回十进制。


1
将我的答案与@NcAdams进行比较,很明显,我将0作为可能的预期结果!
Cam.Davidson.Pilon '18

我不知道您的答案有何不同。如果包含{0,0,0}-> 1,那么{1,1,1}映射到什么?有8种可能性。
AdamO '18年

1
000映射到0,因此我对将0作为可能的值进行了评论。这是在OP编辑之前发布的,几乎同时发布为NcAdams。
Cam.Davidson.Pilon '18

该答案的一半是评论,答案的实际内容仅是链接。请说明您的实际答案,而不只是链接它。
立方

3

永远不会浪费翻转的解决方案,这对于非常偏向的硬币很有帮助。

这种算法的缺点(至少是书面形式)是使用任意精度算法。实际上,您可能要使用它直到整数溢出,然后才将其丢弃并重新开始。

另外,你需要知道什么偏见 ......你可能不哪,也就是说,如果它随温度变化,最喜欢的物理现象。


假设有正面的机会是30%。

  • 从范围开始[1, 8)
  • 翻转硬币。如果是正面,请使用左侧的30%,因此您的新范围是[1, 3.1)。否则,请使用正确的70%,因此您的新范围是[3.1, 8)
  • 重复直到整个范围具有相同的整数部分。

完整代码:

#!/usr/bin/env python3
from fractions import Fraction
from collections import Counter
from random import randrange


BIAS = Fraction(3, 10)
STAT_COUNT = 100000


calls = 0
def biased_rand():
    global calls
    calls += 1
    return randrange(BIAS.denominator) < BIAS.numerator


def can_generate_multiple(start, stop):
    if stop.denominator == 1:
        # half-open range
        stop = stop.numerator - 1
    else:
        stop = int(stop)
    start = int(start)
    return start != stop


def unbiased_rand(start, stop):
    if start < 0:
        # negative numbers round wrong
        return start + unbiased_rand(0, stop - start)
    assert isinstance(start, int) and start >= 0
    assert isinstance(stop, int) and stop >= start
    start = Fraction(start)
    stop = Fraction(stop)
    while can_generate_multiple(start, stop):
        if biased_rand():
            old_diff = stop - start
            diff = old_diff * BIAS
            stop = start + diff
        else:
            old_diff = stop - start
            diff = old_diff * (1 - BIAS)
            start = stop - diff
    return int(start)


def stats(f, *args, **kwargs):
    c = Counter()
    for _ in range(STAT_COUNT):
        c[f(*args, **kwargs)] += 1

    print('stats for %s:' % f.__qualname__)
    for k, v in sorted(c.items()):
        percent = v * 100 / STAT_COUNT
        print('  %s: %f%%' % (k, percent))


def main():
    #stats(biased_rand)
    stats(unbiased_rand, 1, 7+1)
    print('used %f calls at bias %s' % (calls/STAT_COUNT, BIAS))


if __name__ == '__main__':
    main()

3
[0,1]00006666k

单个输出是一样的,对吧?多选好吗?我会按照diff *= 7我的想法编写它……实际上,每次尝试都不需要使用相同的基准。
o11c

是的,如果要单个输出,则相同;如果您要多个,它只会提高效率。
Federico Poloni '18

pp

如果您要单个输出,这绝对会浪费时间。对于公平硬币,标准技术(将硬币滚动三遍,如果您获得TTT,则重复),期望数为24/7 = 3 + 3/7卷。如果使用此算术编码样式技术,则至少滚动四次,除非获得HHH或TTT,否则预期滚动数将超过15/4 = 3 + 3/4。
彼得·索尔

3

正如前面的评论中提到的,这个难题与约翰·冯·诺伊曼(John von Neumann)在1951年发表的论文 “与随机数字有关的各种技术”相关,该论文发表在国家标准局的研究期刊上:

在此处输入图片说明

pf(p)f f(p)=min{1,2p}N


2

这也仅适用于和。p1p0

我们首先使用NcAdams回答的过程将(可能是)不公平硬币变成公平硬币:

翻转硬币两次。如果它降落HHTT,请忽略它,然后再次翻转两次。

现在,硬币有相等的概率出现HTTH。如果出现HT,叫这个H1。如果出现TH,叫这个T1

现在,我们使用公平硬币以二进制形式生成介于和之间的实数。令和。从字符串开始,翻转硬币,然后将结果数字附加到字符串的末尾。重复新的字符串。例如,该序列将为您提供数字。01H1=1T1 =00.H1 H1 T10.110

1/7是一个重复的小数,并且右侧在以2为底的位置,我们得到:

1/7=0.001001001...

2/7=0.010010010...

3/7=0.011011011...

4/7=0.100100100...

5/7=0.101101101...

6/7=0.110110110...

继续翻转公平硬币以生成十进制数字,直到序列中的数字与上述序列之一不匹配为止,然后选择数字,以使生成的数字小于且大于。由于每个生成的数字均具有相同的可能性,因此我们选择了一个介于到之间的数字,且概率相同。nn/7(n1)/717


1
忽略此方法需要进行大量翻转,有趣的是如何将位分成7个可能的部分。这些部分真的同样有可能吗?例如,当您翻转0.000时数字会增加,或者您未翻转的0.001001001最终出现在错误的一侧(这是1/8 + 1/16的情况),还是我看到这个错误?1/7
Sextus Empiricus

1
对最后一个数字不是1/16的进行翻转的概率的校正。因此,您翻转000或001000或001001000,以此类推,概率为1/7k=1(1/8)k=17
Sextus Empiricus

1
因此,在位内终止的概率为(对于否则为零),然后为所需位数的期望值是,与需要位的NcAdams解决方案相比,这不是一个改进。(罪魁祸首是在3位元之后,这种方法仅对25%的案件有决定权)n Ñ33+&Sigma; ñ=31-ŤÑ=4.58T(n)=2n62nn3
3+n=31T(n)=4.5
8733.42
Sextus Empiricus

2

受AdamO的答案启发,这是一个避免偏见的Python解决方案:

def roll(p, n):
    remaining = range(1,n+1)
    flips = 0
    while len(remaining) > 1:
        round_winners = [c for c in remaining if random.choices(['H','T'], [p, 1.0-p]) == ['H']]
        flips += len(remaining)
        if len(round_winners) > 0:
            remaining = round_winners
        p = 1.0 - p
    return remaining[0], flips

这里有两个主要变化:主要变化是,如果所有数字都在一轮中被丢弃,请重复该轮。我也翻转选择正面还是反面意味着每次都丢弃。当p = 0.999时,如果p接近0或1,则所需的翻转次数减少了约70%。


2
“我每次都选择是否意味着抛弃是正面还是反面。这在p = 0.999时p接近0或1的情况下所需的翻转次数减少了70%”-明智的思维!
银鱼'18

1
正面或反面交替绝对比总丢弃头要好-但是,如果在为每个剩余选项掷硬币后,如果它们都相同,然后重复重复全部抛弃,否则可能会更好。与尾部一样多的正面,我们消除了与正面对应的剩余选项,否则,我们消除了与正面对应的剩余选项。
大卫·卡里

2

似乎我们每次都可以更改每次翻转的结果映射。因此,为了方便起见,使用前七个正整数,我们给出以下顺序:

H1
H2

H7
H1

等等

T


APT

PAP(no integers generated)=(1p)7

Nb

CountAP(useless flips)7Nb(1p)7

B(p,n=5)p3(1p)2

PDS(no integers generated)=17p3(1p)2

无用翻转的数量在这里往往会

CountDS(useless flips)5Nb[17p3(1p)2]

AP

CountAP(useless flips)<CountDS(useless flips)

7Nb(1p)7<5Nb[17p3(1p)2]

7(1p)7<5[17p3(1p)2]

p>0.0467AP

pAPDSp0.5967

CountAP(useless flips)CountDS(useless flips)

0.67p=0.10.3p=0.20.127p=0.4


p(0,1)

1
@Sycorax我添加了一些内容,尽管我不确定它是否符合您的建议。
Alecos Papadopoulos

H

1
如果您对(极端伪)“随机”数生成器进行这种解释,就像任何具有相等数量的1,2,3,4,5,6,7的序列一样,那么您也可以不翻转任何硬币并直接采用数字的数字序列12345679999999

1
p17p
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.