本质上,我正在使用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.31
和0.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