【问题标题】:Two dice thrown and its distribution does not correspond with probabilities掷出两个骰子,其分布与概率不对应
【发布时间】:2021-07-28 01:45:16
【问题描述】:

在棋盘游戏 Catan 中,您每回合掷 2 个六面骰子,可能的结果从 2 到 12,并且在 100,000 次掷中时总和的分布应该是这样的:

***CATAN DICE***

2 *****5998

3 ********8170

4 ********8170

5 **********10299

6 ************12283

7 **************14341

8 ************12331

9 **********10149

10 ********8090

11 ******6033

12 ****4068

但是,我只有在使用randint(0, 6) 的骰子是从 0 到 6 的七面时才会得到这个结果。 当我使用randint(1,6) 时,分布如下:

***CATAN DICE***

2 **2771

3 *****5560

4 *****5560

5 ********8410

6 ***********11088

7 **************14132

8 ****************16491

9 *************13768

10 ***********11163

11 ********8220

12 *****5616

这是错误的,8 不太可能出现在一对六面骰子中。 ¿我的代码有问题吗?,¿它可能与 randint() 的工作方式有关吗?

这是我的代码:

from random import randint

print("***CATAN DICE***")

normal = [0,0,0,0,0,0,0,0,0,0,0]

for i in range(0, 100000):
    a=randint(0, 6)
    b=randint(0, 6)
    throw = a+b
    if throw == 2:
        normal[0]+=1        
    if throw == 3:
        normal[1]+=1
    if throw == 3:
        normal[2]+=1
    if throw == 4:
        normal[3]+=1
    if throw == 5:
        normal[4]+=1
    if throw == 6:
        normal[5]+=1
    if throw == 7:
        normal[6]+=1
    if throw == 8:
        normal[7]+=1
    if throw == 9:
        normal[8]+=1
    if throw == 10:
        normal[9]+=1
    if throw == 11:
        normal[10]+=1
i=0
j=0
for i in range(len(normal)):
    print(i+2, end = " ")
    for j in range(int(normal[i]/1000)):
        print("*",end="")
    print(f"{normal[i]}\n")

【问题讨论】:

  • 首先你应该有 randint(1,6) 而不是 randint(0,6)
  • 如果你使用 numpy,你可以这样做:np.unique(np.random.randint(1, 7, [100000, 2]).sum(1), return_counts = True)
  • 我尝试了这两个:randint(1,6) 和 randint (0,6),但是当我使用 1,6 时,我得到 8 的频率更高,这是错误的。
  • 您的问题在于您的if 语句。您有两次出现 if throw == 3:。你的双重5560 是一个提示。
  • 这里没有正态分布。两个离散制服的总和具有离散三角形分布。

标签: python python-3.x distribution dice


【解决方案1】:

您使您的代码比需要的更复杂,并且在此过程中引入了一些错误。我通过计算要直接从结果throw 更新的索引来消除if 语句链。我消除了循环来逐个获取星星,使用舍入而不是整数截断(下限)来获取星星的数量,并右对齐了总和的值。我还将代码分为初始化、生成和输出阶段,以使其易于阅读并易于更改正在运行的试验次数。废话不多说,代码:

from random import randint

# initialize
n = 100000
count = [0 for _ in range(11)]  # less prone to a manual miscount error

# generate : no need for if's, calculate index directly from throw outcome
for i in range(n):
    throw = randint(1, 6) + randint(1, 6)
    count[throw - 2] += 1

# output
print("***CATAN DICE***\n")

for i in range(len(count)):
    stars = "" + "*" * round(count[i] / (n // 100))
    print(f"{i + 2 :>2} " + stars + f"{count[i]}")

产生如下输出:

***CATAN DICE***

 2 ***2741
 3 ******5637
 4 ********8210
 5 ***********11099
 6 **************14068
 7 *****************16659
 8 **************13821
 9 ***********11074
10 ********8365
11 ******5500
12 ***2826

如果您希望骰子结果从 0 到 6 而不是从 1 到 6,那么很容易修改它。


最后,只是为了好玩,这里有一个更通用的实现,所以你可以玩弄骰子的数量和骰子的范围。

from random import randint

# initialize
n = 100000      # trials
num_dice = 2    # number of dice

# low and high values for a die
die_lo = 1
die_hi = 6

min_outcome = num_dice * die_lo
num_outcomes = num_dice * die_hi - min_outcome + 1

# generate : no need for if's, calculate index directly from throw outcome
count = [0 for _ in range(num_outcomes)]
for i in range(n):
    throw = sum(randint(die_lo, die_hi) for _ in range(num_dice))
    count[throw - min_outcome] += 1

# output
print("***CATAN DICE***\n")

for i in range(num_outcomes):
    stars = "" + "*" * round(count[i] / (n // 100))
    print(f"{i + min_outcome :>3} " + stars + f"{count[i]}")

我认为这说明了不硬连线 if 语句链的好处。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多