计算积分:单线解决方案?

时间:2013-02-08 02:57:22

标签: python function integral

我正在开发一个程序来查找函数的积分,其中用户指定矩形的数量,开始和停止。

注意:我使用的是矩形的左端点。

我的功能完美无缺(至少看起来很完美)。但是,我想知道我是否可以为它写一个单行,但不确定如何,因为我正在使用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)/nfloat(x)/nrange函数中实现了虚拟“步骤”。

谢谢!

3 个答案:

答案 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)]])

请注意,integralintegral2之间存在很大差异: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函数生成浮点值列表

案例1: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))])

案例2: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)]

有一种方法可以将其变成完整的单线程集成器。我告诉你我的朋友。