我写了以下函数,用于用辛普森规则估计函数的定积分:
def fnInt(func, a, b):
if callable(func) and type(a) in [float] and type(b) in [float]:
if a > b:
return -1 * fnInt(func, b, a)
else:
y1 = nDeriv(func)
y2 = nDeriv(y1)
y3 = nDeriv(y2)
y4 = nDeriv(y3)
f = lambda t: abs(y4(t))
k = f(max(f, a, b))
n = ((1 / 0.00001) * k * (b - a) ** 5 / 180) ** 0.25
if n > 0:
n = math.ceil(n) if math.ceil(n) % 2 == 0 else math.ceil(n) + 1
else:
n = 2
x = (b - a) / n
ans = 0
for i in range(int((n - 4) / 2 + 1)):
ans += (x / 3) * (4 * func(a + x * (2 * i + 1)) + 2 * func(a + x * (2 * i + 2)))
ans += (x / 3) * (func(a) + 4 * func(a + x * (n - 1)) + func(b))
return ans
else:
raise TypeError('Data Type Error')
但是,似乎每当我尝试使用此函数时,都需要很长时间才能产生输出。有没有办法重写此代码以占用更少的时间?
正如提到的注释之一,分析代码将显示速度变慢。 也许nDeriv
很慢。 如果没有分析工具,则可以在每个代码段周围进行time()
调用并打印结果。 更多信息在这里: 测量 Python 中经过的时间?
因此,如果减速最终出现在您的for
循环中,您可以尝试以下几件事:
-
Python 可能会在每次迭代中计算循环条件:
for i in range(int((n - 4) / 2 + 1)):
在循环之前计算一次int((n - 4) / 2 + 1)
。
- 不要重新计算循环中不会更改的内容。 例如,每次循环迭代都会重新计算
x / 3
,但它永远不会改变。 在循环开始之前执行此操作。
同样,每次循环迭代都要执行两次2 * i
。
-
加法比乘法快。 func 参数可以重写为:
xi = x * i a1 = a + xi + xi + x a2 = a1 + x
然后更进一步,您还可以将xi
作为累加器重新做。 也就是说,从x = 0
开始,然后每次迭代都只是x += x
- 这可能是
- 显而易见的,但如果
func()
难以计算,这个函数将呈指数级缓慢。
Python 可能会为你做很多更简单的优化,所以这些可能没有帮助,只是想分享一些想法。