【问题标题】:Dice rolling outputs掷骰子输出
【发布时间】:2017-11-06 11:46:29
【问题描述】:

我已经完成了这段代码,但我需要帮助理解为什么输出与期望的不同。这是我的代码。我的教授还说要使用 237 的种子。

import random
rng = random.Random()
rng.seed(237)

NumberOfRolls = int(input("How many dice?:"))
NumberOfFaces = int(input("How many sides of each dice?:"))
numberOfTrials = int(input('How many trials? Enter:'))

# Set the number of elements in the list
#def throwDice():
def throwDice(NumberOfRolls):
    return random.randrange(1,NumberOfFaces)

def rollAllDice(NumberOfRolls):
  sum = 0;
  for i in range(NumberOfRolls):
    v = throwDice(NumberOfRolls);
    sum = sum + v;
    # print(v);
  return sum;



# perform simulation, record and print frequencies
index = (NumberOfRolls*NumberOfFaces)+1;
frequency = [0]*index
rel_frequency_list = [0]*index
exp_prob_list =[0]*index

for i in range(numberOfTrials):
  ind = rollAllDice(NumberOfRolls);
  frequency[ind] = frequency[ind]+1;
# end for
print()
#print("Frequencies:")



# calculate relative frequencies, probabilities and errors
relativeFrequency = [0, 0]
probability = [0,0]
error = [0,0]
for i in range(2, len(frequency)):
  rel_frequency_list[i] = frequency[i]/numberOfTrials;
  exp_prob_list[i] = frequency[i]/100;


#print(relativeFrequency)
#print(probability)
#print(error)
print()


# print results
f1 = "{0:<10}{1:<22}{2:<22}{3:<22}"
f2 = 71*"-"
f3 = "{0:>3}       {1:<22.15f}{2:<22.15f}{3:<.15f}"
print(f1.format("Sum","Frequency","Relative Frequency","Experimental Probability"))
print(f2)
for i in range(NumberOfRolls, len(frequency)):
   print(f3.format(i, frequency[i], rel_frequency_list[i], exp_prob_list[i]),"%")
#end for

这是我的 3 个骰子、6 个面、10,000 次试验的输出

Sum       Frequency             Relative Frequency    Experimental Probability

-----------------------------------------------------------------------
  3       75.000000000000000    0.007500000000000     0.750000000000000 %
  4       232.000000000000000   0.023200000000000     2.320000000000000 %
  5       454.000000000000000   0.045400000000000     4.540000000000000 %
  6       831.000000000000000   0.083100000000000     8.310000000000000 %
  7       1214.000000000000000  0.121400000000000     12.140000000000001 %
  8       1468.000000000000000  0.146800000000000     14.680000000000000 %
  9       1491.000000000000000  0.149100000000000     14.910000000000000 %
 10       1445.000000000000000  0.144500000000000     14.449999999999999 %
 11       1157.000000000000000  0.115700000000000     11.570000000000000 %
 12       828.000000000000000   0.082800000000000     8.279999999999999 %
 13       476.000000000000000   0.047600000000000     4.760000000000000 %
 14       230.000000000000000   0.023000000000000     2.300000000000000 %
 15       99.000000000000000    0.009900000000000     0.990000000000000 %
 16       0.000000000000000     0.000000000000000     0.000000000000000 %
 17       0.000000000000000     0.000000000000000     0.000000000000000 %
 18       0.000000000000000     0.000000000000000     0.000000000000000 %

这是所需的(相同的输出):

Sum Frequency Relative Frequency Experimental Probability
----------------------------------------------------------------------
 3 45 0.00450 0.45 %
 4 126 0.01260 1.26 %
 5 281 0.02810 2.81 %
 6 494 0.04940 4.94 %
 7 677 0.06770 6.77 %
 8 968 0.09680 9.68 %
 9 1191 0.11910 11.91 %
 10 1257 0.12570 12.57 %
 11 1257 0.12570 12.57 %
 12 1164 0.11640 11.64 %
 13 932 0.09320 9.32 %
 14 683 0.06830 6.83 %
 15 469 0.04690 4.69 %
 16 282 0.02820 2.82 %
 17 122 0.01220 1.22 %
 18 52 0.00520 0.52 %

【问题讨论】:

  • random.randrange() 的上限是独占的。尝试使用NumberOfFaces + 1。
  • 或试试random.randint() 更简单:)
  • 你的种子也没有像你想象的那样做。使用random.seed(237),然后使用random.randrange() 或randint()。现在你正在设置一个新的 rng 的种子并且从不使用它。
  • 使用 randint 产生更接近和更好的结果。如何使用种子?
  • random.seed(237) 当您调用 random.randint() 它使用内部 rng。您创建了一个新的,但从未使用它 - rng.randint() 会使用它。

标签: python dice


【解决方案1】:

这是一个重组的版本:

from random import Random

def get_int(prompt):
    while True:
        try:
            return int(input(prompt))
        except ValueError:
            pass

class Dice:
    def __init__(self, num_dice, num_faces, seed=None):
        self.num_dice = num_dice
        self.num_faces = num_faces
        self.rng = Random()
        if seed is not None:
            self.rng.seed(seed)

    def roll(self):
        return sum(self.rng.randint(1, self.num_faces) for _ in range(self.num_dice))

    def histogram(self, num_trials):
        hist = [0] * (self.num_dice * self.num_faces + 1)
        for _ in range(num_trials):
            hist[self.roll()] += 1
        return hist

def main():
    num_dice = get_int("How many dice? ")
    num_faces = get_int("How many sides on each die? ")
    num_trials = get_int("How many trials? ")

    dice = Dice(num_dice, num_faces, 237)
    hist = dice.histogram(num_trials)

    print("Sum Frequency Relative Frequency Experimental Probability")
    print("-" * 70)

    lo = num_dice
    hi = num_dice * num_faces
    for n in range(lo, hi + 1):
        freq = hist[n]
        rfreq = freq / num_trials
        print("{:d} {:d} {:0.5f} {:0.2f} %".format(n, freq, rfreq, 100. * rfreq))

if __name__ == "__main__":
    main()

【讨论】:

  • 我不确定 OOP 是否适合这个,而且你的模型对我来说没有意义。 Dice 对象可能不应该具有指示它有多少个骰子的属性。也许class DiceGame?
  • @AdamSmith OOP 在这里不是必要的;它可以很容易地用简单的函数来完成。另一方面,OOP 可以很容易地划分逻辑,更容易思考问题的每一部分,并减少对共享变量的依赖,即 roll() 需要知道多少个骰子和多少个面,但是您不想每次调用时都重新指定。
  • 这对我来说可能是 Johnny-Come-Lately 综合症。最近花了很多时间在 Haskell-land 上,所以突然间 OOP 看起来开销太大了。当你只有一把锤子时,所有的世界都应该是函数——或者类似的东西:D
  • @AdamSmith 用于命名,Dice 如a set of dice 对我来说似乎是惯用的;如果您愿意,当然可以称它为DiceCup。 DiceGame 不太对,因为它没有任何游戏逻辑。 histogram 严格来说应该是一个独立的函数,而不是Dice 的成员。
  • 谢谢!也有人可以帮我删除多余的0吗?例如,整数包括 .00000000 之后。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
  • 1970-01-01
  • 2012-02-29
  • 2015-06-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多