我正在开发一个程序来查找函数的积分,其中用户指定矩形的数量,开始和停止。
注意:我使用的是矩形的左端点。
我的功能完美无缺(至少看起来很完美)。但是,我想知道我是否可以为它写一个单行,但不确定如何,因为我正在使用eval()
。这是我的原始代码:
def integral(function, n=1000, start=0, stop=100):
"""Returns integral of function from start to stop with 'n' rectangles"""
increment, rectangles, x = float((stop - start)) / n, [], start
while x <= stop:
num = eval(function)
rectangles.append(num)
if x >= stop: break
x += increment
return increment * sum(rectangles)
这很好用:
>>> integral('x**2')
333833.4999999991
实际答案是1000000/3
,所以我的函数给出了一个非常好的估计(仅1000个矩形)。
我尝试一行:
def integral2(function, n=1000, start=0, stop=100): rectangles = [(float(x) / n) for x in range(start*n, (stop*n)+1)]; return (float((stop-start))/n) * sum([eval(function) for x in rectangles])
然而,由于我使用的是分号,这不是真正的单行。此外,它有点慢(需要几秒钟,这是非常重要的)并给出错误的答案:
>>> integral2('x**2')
33333833.334999967
那么,是否可以使用单线解决方案来实现此功能?我不确定如何在同一列表理解中实现eval()
和float(x)/n
。 float(x)/n
在range
函数中实现了虚拟“步骤”。
谢谢!
答案 0 :(得分:2)
def integral2(function, n=1000, start=0, stop=100): return (float(1)/n) * sum([eval(function) for x in [(float(x) / n) for x in range(start*n, (stop*n)+1)]])
请注意,integral
和integral2
之间存在很大差异:integral2
制作(stop*n)+1-(start*n)
矩形,而integral
仅制作n
矩形
In [64]: integral('x**2')
Out[64]: 333833.4999999991
In [68]: integral2('x**2')
Out[68]: 333338.33334999956
In [69]: %timeit integral2('x**2')
1 loops, best of 3: 704 ms per loop
In [70]: %timeit integral('x**2')
100 loops, best of 3: 7.32 ms per loop
integral
的翻译可能更具可比性:
def integral3(function, n=1000, start=0, stop=100): return (float(stop-start)/n) * sum([eval(function) for x in [start+(i*float(stop-start)/n) for i in range(n)]])
In [77]: %timeit integral3('x**2')
100 loops, best of 3: 7.1 ms per loop
当然,应该说,除了(乖张?)娱乐之外,没有任何目的可以使它成为一个单行:)
答案 1 :(得分:2)
如果您收到eval
作为Python function
本身,则无需使用callable
您还可以使用numpy.arange
函数生成浮点值列表
function
是Python callable
def integrate(f, n, start, end):
return sum([f(i)*(abs(start-end)/float(n)) for i in np.arange(start, end, abs(start-end)/float(n))])
function
不是Python callable
def integrate(f, n, start, end):
return sum([eval(f)*(abs(start-end)/float(n)) for x in np.arange(start, end, abs(start-end)/float(n))])
答案 2 :(得分:0)
使用numpy的linspace作弊怎么样?
integrate = lambda F, n0, nf: sum([F(x)*(abs(nf-n0)/(abs(nf-n0)*300))for x in np.linspace(n0, nf, abs(nf-n0)*300)])
它取一个函数F,一个下限n0和一个上限nf。以下是0到5之间x ** 2的工作原理:
In [31]: integrate(lambda x: x**2, 0, 5)
Out[31]: 41.68056482099179
非常接近。
编辑:这是我的linspace one liner。linspace = lambda lo, hi, step:[lo + (hi-lo)/step*i + (hi-lo)/(step*step-1)*i for i in range(step)]
有一种方法可以将其变成完整的单线程集成器。我告诉你我的朋友。