我的Python概率计算器有问题



本质上,我正在使用Python制作一个概率计算器。这是指在进行了一定数量的实验后找到一定数量球的概率(可能是一个很大的数字(,在每个实验中,你从帽子上随机抽取一定数量的球。我在Hat类下使用了面向对象编程来实现这一点。帽子对象可以通过以下方式创建:

hat = Hat(blue=3,red=2,green=6)

该类应该采用可变数量的参数,这些参数指定帽子中每种颜色的球的数量。此处帽子包含3 blue balls, 2 red balls and 6 green balls.

在类外,有一个名为experience的函数,当您在执行了一定数量的实验(num_experiments(后决定绘制一定数量的球时,该函数从名为'hat'的参数中计算出绘制特定类型球[预期球]的概率。特定的球可以是不同颜色或风格的球。因此,调用实验函数的一种典型方式/示例是:

probability = experiment(hat=hat, expected_balls={"blue":2,"green":1}, num_balls_drawn=4, num_experiments=1000)

每次运行代码时产生的概率应该略有不同。我用这个对象和特定的函数调用测试我的代码:

hat = Hat(blue=3,red=2,green=6)
probability = experiment(hat=hat, expected_balls={"blue":2,"green":1}, num_balls_drawn=4, num_experiments=1000)

虽然我的概率变化很小,产生的概率在0.310.39之间,但预期的概率实际上是0.272或接近该概率的值(相差0.01(。所以看起来我离得很远。然而,我不太清楚问题是什么以及如何解决。

任何帮助都将不胜感激!提前谢谢。

代码


import copy
import random
class Hat:

def __init__(self,**ball):
self.contents = list() #holds the balls
ball_and_count = list() #list for colour of ball and its count 
for key, value in ball.items():
ball_and_count.append(f"{key}= {value}")
#print(ball_and_count)
for i in ball_and_count:
equal_pos = i.find("=")
ball_type = i[:equal_pos] #using string splicing to find ball type
count = int(i[equal_pos+1:])#using string splicing to find the number of balls of that type
c = 0
while c < count:
self.contents.append(ball_type)
c = c + 1
def draw(self,num)
self.num = num
c = 0 #used in a while loop
drawed_ball = list() #this is where all the balls that were drawed out from contents will stay
try:
while c < self.num:
drawed_ball.append(self.contents.pop(random.randint(0,len(self.contents)-1)))
c = c + 1
return drawed_ball
except:
return drawed_ball

def experiment(hat, expected_balls,num_balls_drawn, num_experiments):
M = 0
exp_done = 0
while exp_done < num_experiments:
drawn = 0
drawn_balls = list()
while drawn < num_balls_drawn:
dc_contents = copy.deepcopy(hat.contents) # we are creating a deep copy of hat contents so that hat.contents stays the same
drawn_balls.append(dc_contents.pop(random.randint(0,len(dc_contents)-1))) #append to the drawn_balls list
v = 0
for key, val in expected_balls.items():
if key in drawn_balls:
k = drawn_balls.count(key) 
if k >= val:#here we are checking if for one ball type, we are drew the expected number of balls, then we increment the variable v
v = v + 1

if v == len(expected_balls):#we check if we have drawn the expected no. balls for all the balls and types, either we did or we did not, no in between, then we increment the variable M
M = M + 1            

#incrementing the number of balls drawn  
drawn = drawn + 1
exp_done = exp_done + 1 #incrementing the number of experiments drawn

N = num_experiments
prob = M / N
return prob

有更有效的方法来解决这个问题,但遵循您的原始结构:

def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
exp_done = 0
M = 0
while exp_done < num_experiments:
drawn = 0
drawn_balls = list()
dc_contents = copy.deepcopy(
hat.contents)  # we are creating a deep copy of hat contents so that hat.contents stays the same
while drawn < num_balls_drawn:
drawn_balls.append(
dc_contents.pop(random.randint(0, len(dc_contents) - 1)))  # append to the drawn_balls list
for key, val in expected_balls.items():
if drawn_balls.count(key) < val:
break
else:
M += 1
break
drawn += 1
exp_done += 1  # incrementing the number of experiments drawn
N = num_experiments
prob = M / N
return prob

必须解决的问题:

  • 每次出球后都要重置帽子,deepcopy需要在圈外
  • 只要抽到每一个所需的类型,你的检查程序就会计算成功

可运行:

import copy
import random
class Hat:
def __init__(self,**ball):
self.contents = list() #holds the balls
ball_and_count = list() #list for colour of ball and its count
for key, value in ball.items():
ball_and_count.append(f"{key}= {value}")
#print(ball_and_count)
for i in ball_and_count:
equal_pos = i.find("=")
ball_type = i[:equal_pos] #using string splicing to find ball type
count = int(i[equal_pos+1:])#using string splicing to find the number of balls of that type
c = 0
while c < count:
self.contents.append(ball_type)
c = c + 1
def draw(self,num):
self.num = num
c = 0 #used in a while loop
drawed_ball = list() #this is where all the balls that were drawed out from contents will stay
try:
while c < self.num:
drawed_ball.append(self.contents.pop(random.randint(0,len(self.contents)-1)))
c = c + 1
return drawed_ball
except:
return drawed_ball

def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
exp_done = 0
M = 0
while exp_done < num_experiments:
drawn = 0
drawn_balls = list()
dc_contents = copy.deepcopy(
hat.contents)  # we are creating a deep copy of hat contents so that hat.contents stays the same
while drawn < num_balls_drawn:
drawn_balls.append(
dc_contents.pop(random.randint(0, len(dc_contents) - 1)))  # append to the drawn_balls list
for key, val in expected_balls.items():
if drawn_balls.count(key) < val:
break
else:
M += 1
break
drawn += 1
exp_done += 1  # incrementing the number of experiments drawn
N = num_experiments
prob = M / N
return prob

hat = Hat(blue=3,red=2,green=6)
probability = experiment(hat=hat, expected_balls={"blue":2,"green":1}, num_balls_drawn=4, num_experiments=1000)
print(probability)

这会打印像0.288这样的值——对我来说,如何获得像8.0这样的值是个谜,但我很确定这实际上不是你正在运行的代码。(因此,您没有运行代码中给出的解决方案——它仍然有拼写错误,无论如何都不会在def draw(self,num)上运行(

我终于修复了它!我松了一口气。我只是在Hat类中对绘图方法做了一些调整。然后我在实验函数中使用了draw方法,以及你(Grismar(提到的变化。非常感谢!

import copy
import random
class Hat:

def __init__(self,**ball):
self.contents = list() #holds the balls
ball_and_count = list() #list for colour of ball and its count 
for key, value in ball.items():
ball_and_count.append(f"{key}= {value}")
#print(ball_and_count)
for i in ball_and_count:
equal_pos = i.find("=")
ball_type = i[:equal_pos] #using string splicing to find ball type
count = int(i[equal_pos+1:])#using string splicing to find the number of balls of that type
c = 0
while c < count:
self.contents.append(ball_type)
c = c + 1

def draw(self,num):
self.num = num
c = 0 #used in a while loop
drawed_ball = list() #this is where all the balls that were drawed out from contents will stay
if self.num <= len(self.contents):
while c < self.num:
drawed_ball.append(self.contents.pop(random.randint(0,len(self.contents)-1)))
c = c + 1
return drawed_ball
else:
drawed_ball = self.contents
return drawed_ball

def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
exp_done = 0
M = 0
while exp_done < num_experiments:
dc_contents = copy.deepcopy(hat)  # we are creating a deep copy of hat contents so that hat.contents stays the same
drawn_balls = dc_contents.draw(num_balls_drawn)

for key,val in expected_balls.items():
if drawn_balls.count(key) < val:
break

else:
M += 1

exp_done += 1  # incrementing the number of experiments drawn
N = num_experiments
prob = M / N
return prob

最新更新