【问题标题】:How do I print the variable values that result in the maximum of a function?如何打印导致函数最大值的变量值?
【发布时间】:2018-03-22 19:08:03
【问题描述】:

我想在 python 中计算一个函数的最大值,然后打印最大值,以及该最大值处的变量值。

我想我已经走得很远了。在下面的示例中,该函数只是来自x 的值乘以来自y 的值再乘以来自z 的值(理论上这个函数可以是任何值)。其中最大值为3 * 6 * 9 = 162

我的问题是:如果这些列表有数百个数字,我真的不想打印整个输入列表,这可能是一个包含数十万条目的庞大列表。

我只对最后一组值感兴趣(这里是3 6 9),但我似乎无法弄清楚如何只打印这组值。

任何帮助将不胜感激。

谢谢!

p=[1,2,3]
q=[6,5,4]
r=[7,8,9]

def f(x,y,z):
    maximum=0
    for a in x:
        for b in y:
            for c in z:
                if a*b*c > maximum:
                    maximum = a*b*c
                    print (a,b,c)
    print (maximum)  

f(p,q,r)

结果:

1 6 7
1 6 8
1 6 9
2 6 7
2 6 8
2 6 9
3 6 7
3 6 8
3 6 9
162

【问题讨论】:

  • 根据定义,最后一项是您的最大值。
  • 当然,但我*只想要值 3 6 9 而不是上面的列表

标签: python python-3.x function math max


【解决方案1】:

最简单的方法是像跟踪当前最大值一样跟踪值:

定义 f(x,y,z): 最大值 = 0 对于 x 中的 a: 对于 y 中的 b: 对于 z 中的 c: 如果 a*b*c > 最大值: 最大值 = a*b*c a_max = a b_max = b c_max = c 打印(a_max,b_max,c_max) 打印(最大)

您可以通过使用不同于一开始设置maximum = 0 的技术来使您的代码更加健壮。例如,如果您的列表只有负数怎么办?结果将是错误的。您可以使用所谓的标记值(如None)来指示第一次迭代。哨兵是指示“无效”值的标记。这将确保始终找到正确的最大值:

定义 f(x,y,z): 最大值 = 对于 x 中的 a: 对于 y 中的 b: 对于 z 中的 c: 如果 最大值为无 a*b*c > 最大值: 最大值 = a*b*c abc_max = (a, b, c) 打印 (*abc_max, sep=', ') 打印(最大)

您可以通过返回您感兴趣的数字来改进您的代码设计,而不仅仅是打印它们。这将允许您以任何您想要的方式操作它们,包括在之后打印它们。 Python 允许使用元组返回多个值,因此您可以执行以下操作:

定义 f(x,y,z): 最大值 = 无 对于 x 中的 a: 对于 y 中的 b: 对于 z 中的 c: 如果最大值为无或 a*b*c > 最大值: 最大值 = a*b*c abc_max = (a, b, c) 返回最大值,abc_max 最大值, pqr = f(p, q, r) 打印(*pqr, sep=', ') 打印(最大)

您可能要考虑的优化不是多次评估您的“功能”。这对于不两次返回相同值的更复杂的情况和函数尤其重要。您可以将 if 块的开头替换为类似

...
current_value = a * b * c
if current_value > maximum:
    maximum = current_value
    ...

如果你真的有兴趣在任意函数上进行这项工作,你可以使用 Python 来做到这一点。函数是对象,可以像列表、数字和字符串一样传递:

定义 f(fn, x, y, z): 最大值 = 无 对于 x 中的 a: 对于 y 中的 b: 对于 z 中的 c: 当前 = fn(a, b, c) 如果最大值为无或当前 > 最大值: 最大值 = 当前 abc_max = (a, b, c) 返回最大值,abc_max 最大值, pqr = f(λ x, y, z: x * y * z, p, q, r)

如果您对进一步的概括感兴趣,可以查看itertools,它具有函数product,用于运行嵌套for 循环的“扁平化”版本。这将允许您接受任意数量的输入迭代,而不仅仅是三个。 Python 允许在参数列表中使用* 任意数量的位置参数。名称中带有* 的参数将是所有剩余位置参数的元组。它也可以在 lambda 中使用:

从 functools 导入减少 从 itertools 导入产品 从操作员导入 mul def f(fn, *iterables): max_values = max(product(*iterables), key=lambda x: fn(*x)) 返回 fn(*max_values), max_values 最大值, pqr = f(lambda *args: reduce(mul, args), p, q, r)

您可以考虑添加一个比较器来做一些除了计算最大值之外的事情。但是,这实际上是多余的,因为您可以使用正确实现的fn 将任何其他操作转换为最大计算量。这与根据键而不是比较器实现 Python 排序函数的逻辑相同。在上面的示例中,您可以通过翻转键的符号来找到最小值:lambda *args: -reduce(mul, args)。您可以使用lambda *args: -abs(sum(args) - reduce(mul, args)) 之类的内容找到乘积最接近其总和的组合。可能性是巨大的。

这里是一个 IDEOne 示例的链接,该示例演示了上面显示的最后一个版本:https://ideone.com/QNj55T。 IDEOne 是一个用于炫耀或测试小型 sn-ps 的便捷工具。我与它没有从属关系,但我经常使用它。

【讨论】:

  • @JaneWatson。很高兴看到您自己为此付出了很多努力。
  • @JaneWatson。一旦出现有帮助的答案,即使是你自己的,也接受答案是很正常的。
  • 再过 2 天不让我。
【解决方案2】:

事实证明,把问题写出来是解决问题的好方法。还是谢谢!

def f(x,y,z):
    maximum=0
    for a in x:
        for b in y:
            for c in z:
                if a*b*c > maximum:
                    j=(a,b,c)
                    maximum = a*b*c
    print (maximum)
    print (j)

【讨论】:

    【解决方案3】:

    这是一个更精简的解决方案,pythonic,因为您希望这是一个学习示例。我还大量评论,以便您可以跟进:

    # importing this is necessary in python3 as `reduce` was removed in python3
    import functools
    
    p = [1,2,3]
    q = [6,5,4]
    r = [7,8,9]
    
    def f (x,y,z):
    
        # 1. Combine the list arguments together into 1 list "[x,y,z]"
        # 2. Iterate over each list in the group of lists "for li in [x,y,z]"
        # 3. Get the max number within each list "max(li)"
        # 4. Assign the resulting list to the maxv variable "maxv = ..." yielding [3,6,9]
        maxv = [max(li) for li in [x,y,z]]
    
        # Print the 3 largest integers used to multiply next
        print( maxv )
    
        # Use reduce to multiply each list element by themselves
        product = functools.reduce(lambda x,y: x*y, maxv)
    
        # Print the output = 162 in this case
        print( product )
    
    f(p,q,r)    
    

    更新

    如果你不知道有多少个整数列表将被传递到函数中(可能超过 3 个),你可以遍历整个参数处理程序并将其作为你的列表而不是编码 [x,y,z],就像这样:

    p = [1,2,3]
    q = [6,5,4]
    r = [7,8,9]
    s = [8,9,10]
    t = [9,10,11]
    
    def d (*args):
        maxv = [max(li) for li in [x for x in args]]
        print( maxv )
        product = functools.reduce(lambda x,y: x*y, maxv)
        print( product )
    
    d(p,q,r)   # yields 162
    d(p,q,r,s) # yields 1620
    d(p,q,r,s,t) # yeilds 17820
    

    【讨论】:

    • 有点违背了问题中给出的“理论上这个功能可以是任何东西”的目的......
    • 仍然是一个不错的解决方案。
    • 好吧,他想将这些值“相乘”,所以我们知道它只会包含整数。我想说让这更多dynamic 的唯一方法是创建一个参数迭代器,将所有可能的参数(如果给出超过 3 个)组合到一个列表中,而不是硬编码[x,y,z]
    • 最好的方法是传入你的函数来组合值,你的函数将它们与当前的“最大值”和你的任意迭代列表进行比较。
    • @MadPhysicist 演示?
    猜你喜欢
    • 2015-02-20
    • 1970-01-01
    • 2021-01-12
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    • 1970-01-01
    • 2020-09-19
    • 1970-01-01
    相关资源
    最近更新 更多