【问题标题】:Why is my code inaccurate when using list comprehension?为什么我的代码在使用列表理解时不准确?
【发布时间】:2020-11-18 17:36:05
【问题描述】:

我正在学习 python 并正在尝试以下question。这是我想出的代码:

import numpy as np

def f(x):
    return x**3-3*x**2-5.5*x+25

x = np.linspace(-3,5,10000)

for i in x:
    if f(i)>f(i-1) and f(i)>f(i+1):
        max=i
    if f(i)<f(i-1) and f(i)<f(i+1):
        min=i
print('Coordinates for maxima: ({:.3f},{:.3f})'.format(max,f(max)))
print('Coordinates for minima: ({:.3f},{:.3f})'.format(min,f(min)))

但是,输出超出了我想要的答案,所以我弄乱了它,当我使用以下循环时它完美地工作:

for i in range(1,len(x)-1):
    if f(x[i])>f(x[i-1]) and f(x[i])>f(x[i+1]):
        max=x[i]
    if f(x[i])<f(x[i-1]) and f(x[i])<f(x[i+1]):
        min=x[i]

所以我的问题是为什么第二个循环比第一个更好?我认为这两种方法会有相同的输出。

【问题讨论】:

  • 您的代码不一样。在您的第二个代码中,您增加/减少索引,在您的第一个代码中,值。
  • 另外,您的第二个版本跳过了x 中的第一个元素。
  • @jasonharper - 最后一个元素。否则会产生index out of bounds 错误。
  • 没有列表理解。

标签: python loops list-comprehension


【解决方案1】:

如果您使用间隙(即数组 x 的相邻元素之间的差异)而不是用 1 递增或递减 i,那么此代码将等效于以下代码(忽略边界条件,-3 和 5)。检查下面的代码以供参考。

import numpy as np

def f(x):
    return x**3-3*x**2-5.5*x+25

x = np.linspace(-3,5,10000)
gap = x[1] - x[0]

for i in x:
    if f(i)>f(i-gap) and f(i)>f(i+gap):
        max=i
    if f(i)<f(i-gap) and f(i)<f(i+gap):
        min=i
print('Coordinates for maxima: ({:.3f},{:.3f})'.format(max,f(max)))
print('Coordinates for minima: ({:.3f},{:.3f})'.format(min,f(min)))

【讨论】:

  • 好吧,对于这个特定的输入数据。一般不会。
  • 您的解决方案适用于均匀分布的数据,但通常不适用。
【解决方案2】:

首先,您没有使用列表推导。二、循环表达式

for i in x:
    if f(i)>f(i-1)...

for i in range(1,len(x)-1):
    if f(x[i])>f(x[i-1]) ...

意思不同。

首先,第一个循环所有x的元素,而第二个循环几乎x的所有元素,但不包括第一个和最后一个元素。

其次,f(i-1)(其中ix 的一个元素)和f(x[i-1])(其中i 是一个索引)表示不同的东西。您似乎认为第一个循环中的f(i-1) 相当于第二个循环中的f(x[i-1]),而实际上它实际上相当于f(x[i] - 1)注意-1 相对于括号] 的位置。

【讨论】:

    【解决方案3】:

    首先,你的界限不一样。但此外,使用正确的循环,您正在评估由 linespace 参数给出的相邻横坐标值(大约 8/10000)。使用不正确的循环,您正在评估由正负 1 的横坐标值分隔的点。

    如果我们忽略第一个问题,虽然算法不正确,但在这个例子中并不重要,因为在 -3 或 5 处没有局部最小值:

    import numpy as np
    
    def f(x):
        return x**3-3*x**2-5.5*x+25
    
    x = list(np.linspace(-3,5,10000))
    delta = 8/10000 #
    
    for i in x:
        if f(i)>f(i-delta) and f(i)>f(i+delta):
            max=i
        if f(i)<f(i-delta) and f(i)<f(i+delta):
            min=i
    print('Coordinates for maxima: ({:.3f},{:.3f})'.format(max,f(max)))
    print('Coordinates for minima: ({:.3f},{:.3f})'.format(min,f(min)))
    

    【讨论】:

    • 这与 Alok Nayak 的答案几乎相同,但有一个额外的缺点是 x[0]x[1] 之间的差距是硬编码的,而不是从 x 计算出来的。
    • @jmramsey 你当然是正确的。但是 OP 提出的问题是为什么他的一种方法会产生错误的结果。答案是他没有查看相邻的横坐标值,这才是真正的重点。而我的delta 值实际上只是一个极好的近似值,在这种情况下有效。但是这段代码(就像 Alok 发布的代码一样)仍然是错误的,因为边界条件仍然是错误的,并且无论如何都不能按原样使用。它只是作为 OP 出错的证据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-01
    • 2020-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-15
    • 1970-01-01
    相关资源
    最近更新 更多