print("Getting possible numbers")
import random
h1 = random.uniform(0,30)
h2 = random.uniform(0,30)
h3 = random.uniform(0,30)
t = random.uniform(0,30)
baset = .5 * t * h3
volumeti = baset * h2
baser = t * h2
volumer = h1 * baser
volumetotal = volumeti + volumer
c = 1
if volumetotal == 187.2:
print("h1=", h1, "h2=", h2, "h3=", h3, "t=", t)
while volumetotal != 187.2:
c += 1
print("Wrong, trying again", c)
它会找到六角棱镜的体积,但需要很长时间,而我还没有输出。
答案 0 :(得分:4)
循环:
while volumetotal != 187.2:
c += 1
print("Wrong, trying again", c)
是一个陷阱。一旦进入循环,你永远不会离开,因为你没有在循环体中改变volumetotal
。
另请注意,检查浮点数的相等性可能很棘手。两个数字可以非常接近(10 ** 16中的1个部分)并且仍然不同 - 并且这个大小的数字错误一直在发生。
答案 1 :(得分:1)
你可能永远不会得到输出。
更好的解决方案是解决方程,以便您可以随机选择3个数字并解决第四个问题。也许像:
187.2 = .5 * t * h3 * h2 + h1 * t * h2
187.2 = h2(.5 * t * h3 + h1 * t)
h2 = 187.2 / (.5 * t * h3 + h1 * t)
然后生成t
,h3
,h1
并计算h2
import random
print("Getting possible numbers")
h1 = random.uniform(0,30)
h3 = random.uniform(0,30)
t = random.uniform(0,30)
h2 = 187.2 / ((.5 * t * h3) + (h1 * t))
print("h1=", h1, "h2=", h2, "h3=", h3, "t=", t)
答案 2 :(得分:1)
你也必须循环获取新的随机变量。此外,在处理浮点变量时,您必须接受一些小错误。看看这个:
print("Getting possible numbers")
import random
volumetotal = 0
c = 0
while abs(volumetotal - 187.2) >= 0.1:
c += 1
print("Attempt ", c)
h1 = random.uniform(0,30)
h2 = random.uniform(0,30)
h3 = random.uniform(0,30)
t = random.uniform(0,30)
baset = .5 * t * h3
volumeti = baset * h2
baser = t * h2
volumer = h1 * baser
volumetotal = volumeti + volumer
print("h1=", h1, "h2=", h2, "h3=", h3, "t=", t)
答案 3 :(得分:0)
修复无限循环问题后,您可以使用以下检查:
error = 0.00001
expected = 187.2
if expected - error <= volumetotal <= expected + error:
print("Yay, this is roughly correct.")
另一个技巧,但是这个减少运行时间的方法是跟踪先前选择的随机变量并在尝试失败后将它们设置为上限/下限。因此:
# Pseudo-code
# if expected > desired:
# set previously chosen random variables as the upper bound on the next
# iteration's random ranges.
# else:
# set previously chosen random variables as the lower bound on the next
# iteration's random ranges.
# Be sure to only shrink the range of the random selection until you converge on
# a solution.
答案 4 :(得分:0)
你无法测试两个浮点之间的相等性,因为浮点艺术品的准确性较差。您必须设置一个限制解决方案精度的epsilon值:
print("Getting possible numbers")
import random
import math
epsilon = 0.001
c = 1
h1 = 0
h2 = 0
h3 =0
t = 0
def solve():
h1 = random.uniform(0,30)
h2 = random.uniform(0,30)
h3 = random.uniform(0,30)
t = random.uniform(0,30)
baset = .5 * t * h3
volumeti = baset * h2
baser = t * h2
volumer = h1 * baser
volumetotal = volumeti + volumer
return volumetotal, h1, h2, h3, t
while math.fabs(volumetotal - 187.2) > epsilon:
global h1
global h2
global h3
global t
c += 1
volumetotal, h1, h2, h3, t = solve()
print("Wrong, trying again", c)
print("found a solution : ")
print("h1=", h1, "h2=", h2, "h3=", h3, "t=", t)
编辑:添加输出全局变量。
然而,这是解决方程式的一种非常差的方法。我建议您查找gradient descent确定性算法或genetic algorithms,如果您想以随机方式保留。
答案 5 :(得分:0)
你有几个问题:
False
时,您的比较将评估为True
(例如,.3 + .3 + .3 == .9
的评论中的eumiro示例1}}评估为False
)。第一个问题的解决方案很简单:您只需要确保每次循环都重新计算变量。第二个就是这么简单:你需要测试值是否“足够接近”,而不是测试相等性。因此,选择一个公差值并将您的错误与之比较,而不是要求完美。这两个都显示在下面的代码中(为了清楚起见,我将一些部分拆分成了它们自己的函数)。我也这样做了c
每5000次迭代只打印一次,实际上是makes the whole thing run many times faster。
print("Getting possible numbers")
import random
def get_variables():
'''Initialize some random values.'''
h1 = random.uniform(0,30)
h2 = random.uniform(0,30)
h3 = random.uniform(0,30)
t = random.uniform(0,30)
return h1, h2, h3, t
def calculate_volume(h1, h2, h3, t):
'''Calculate the volume based on the given values.'''
baset = .5 * t * h3
volumeti = baset * h2
baser = t * h2
volumer = h1 * baser
volumetotal = volumeti + volumer
return volumetotal
volumetotal = 0
c = 0
tolerance = 0.00001 # Set the tolerance here!
h1 = h2 = h3 = t = None
while abs(volumetotal - 187.2) >= tolerance:
c += 1
if c % 5000 == 0:
print("Attempt ", c)
h1, h2, h3, t = get_variables()
volumetotal = calculate_volume(h1, h2, h3, t)
print ('h1 = {}\nh2 = {}\nh3 = {}\nt = {}\nc = {}\nv = {}'.format(
h1, h2, h3, t, c, volumetotal))
注意第26行,其中while循环将abs(volumetotal - 187.2)
(结果与预期结果的差异)与0.00001
(公差)进行比较。您可以将此容差设置为您喜欢的任何值,但容差越小,程序运行的时间就越长。
只是为了好玩,您真正想要的是为输出(h1
,h2
等选择精确度,等等)。然后,您可以预测性地增加变量,直到达到容差范围内,而不是使用随机数。这可能是我这样做的方式,而不是使用randoms,因为它至少可以保证你的循环终止,并且它可以更好地控制你的输入/输出。
print("Getting possible numbers")
import itertools
def get_variable_permutations(precision):
'''Get a permutation generator. The precision is # of decimal places.'''
stepsize = 0.1**precision
all_values = (v*stepsize for v in xrange(int(30/stepsize)))
return itertools.permutations(all_values, 4)
def calculate_volume(h1, h2, h3, t):
'''Calculate the volume based on the given values.'''
baset = .5 * t * h3
volumeti = baset * h2
baser = t * h2
volumer = h1 * baser
volumetotal = volumeti + volumer
return volumetotal
volumetotal = 0
c = 0
tolerance = 0.00001
precision = 5 # decimal place precision for h1, h2, h3, and t
for h1, h2, h3, t in get_variable_permutations(precision):
c += 1
if c % 5000 == 0: # So much faster!
print("Attempt ", c)
volumetotal = calculate_volume(h1, h2, h3, t)
if abs(volumetotal - 187.2) <= tolerance:
break
print ('h1 = {}\nh2 = {}\nh3 = {}\nt = {}\nc = {}\nv = {}'.format(
h1, h2, h3, t, c, volumetotal))
你最大的加速(到目前为止)实际上来自减少print
陈述。我的机器在不到一秒的时间内运行上面的代码(在0.00001的公差和h1,h2,h3和t的5位小数的精度)(在~431,000次迭代时找到几乎精确的解)。打印每一行时,相同的计算大约需要40秒。