你有几个问题:
- 首先也是最关键的,你的循环永远不会改变变量的值,所以它永远不会退出(因为它只是无限期地执行相同的测试。
- 其次,几乎同样重要的是,如果您希望程序终止,则不应循环比较浮点数。这是因为浮点表示本质上是不准确的,因此您的比较将按照
False
您可能期望的那样进行评估True
(例如 eumiro 在.3 + .3 + .3 == .9
评估 to的评论中的示例False
)。
第一个问题的解决方案很简单:您只需确保每次循环都重新计算变量。第二个同样简单:您需要测试值是否“足够接近”,而不是测试相等性。因此,选择一个容差值并将您的错误与该值进行比较,而不是要求完美。这两个都显示在下面的代码中(为了清楚起见,我将一些部分拆分为它们自己的函数)。我也做到了,所以c
每 5000 次迭代才打印一次,这实际上使整个事情的运行速度提高了很多倍。
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
等)。然后,您可以不使用随机数,而是以可预测的方式递增变量,直到达到容差范围内。这可能是我这样做的方式,而不是使用随机数,因为它至少保证您的循环将终止,并且它提供了对您的输入/输出的更多控制。
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 秒。