【问题标题】:Calculating the area underneath a mathematical function计算数学函数下方的面积
【发布时间】:2011-01-22 02:09:13
【问题描述】:

我有一系列数据,我使用 Python 中的 2 次多项式进行了近似计算。我想计算这个多项式下面的面积在 0 到 1 之间。

是否有我可以使用的微积分或 numpy 中的类似包,或者我应该只制作一个简单的函数来集成这些函数?

我有点不清楚定义数学函数的最佳方法是什么。

谢谢。

【问题讨论】:

  • 如果是 2 次多项式,只需手动积分即可 - 无需使用代码。
  • 这是针对大量多项式的,我分批处理 40 个。
  • 2次多项式曲线下的面积是1次多项式。只需将值代入该方程即可。
  • @S.Lott 是 3 级,但是是的。
  • @Paul Hankin:哎呀——出于某种原因,我在考虑多项式在每个点的导数。

标签: python polynomial-math numerical-integration


【解决方案1】:

如果您只积分多项式,则不需要表示一般数学函数,请使用 numpy.poly1d,它有一个 integ 积分方法。

>>> import numpy
>>> p = numpy.poly1d([2, 4, 6])
>>> print p
   2
2 x + 4 x + 6
>>> i = p.integ()
>>> i
poly1d([ 0.66666667,  2.        ,  6.        ,  0.        ])
>>> integrand = i(1) - i(0) # Use call notation to evaluate a poly1d
>>> integrand
8.6666666666666661

要集成任意数值函数,您可以将scipy.integrate 与普通 Python 函数一起用于函数。对于分析集成功能,您将使用sympy。在这种情况下,这听起来不像你想要的,尤其是后者。

【讨论】:

  • 太好了 - 谢谢!这是非常有用的。因此,为了计算从 0 到 1 的面积,我可以使用:Area = i(1) - i(0) ?
  • 这将是从0到1的定积分。在这种情况下,这与面积相同,但在某些情况下(部分或全部多项式为负),它不是.
【解决方案2】:
scipy.integrate 中的

'quad' 是用于在一定区间内积分单个变量的函数的通用方法。在一个简单的情况下(例如您的问题中描述的那个),您分别传入您的函数以及下限和上限。 'quad' 返回一个由积分结果和误差项上限组成的元组。

from scipy import integrate as TG

fnx = lambda x: 3*x**2 + 9*x    # some polynomial of degree two
aoc, err = TG.quad(fnx, 0, 1)

[注意:在我发布这个之后,我在我之前发布了一个答案,它表示在 Numpy 中使用“poly1d”的多项式。我上面的 scriptlet 也可以接受这种形式的多项式:

import numpy as NP

px = NP.poly1d([2,4,6])
aoc, err = TG.quad(px, 0, 1)
# returns (8.6666666666666661, 9.6219328800846896e-14)

【讨论】:

  • 由于多项式可以简单地解析积分,因此最好使用更有效的integ方法,而不是对其进行重复的高斯求积。
【解决方案3】:

针对您的特殊情况诉诸通用数值积分算法可能有点矫枉过正……如果您计算出代数,则有一个简单的表达式可以为您提供面积。

你有一个 2 次多项式:f(x) = ax2 + bx + c

您想在 [0,1] 范围内找到 x 曲线下的面积。

反导数F(x) = ax3/3 + bx2/2 + cx + C

从0到1的曲线下面积为:F(1) - F(0) = a/3 + b/2 + c

因此,如果您只计算区间 [0,1] 的面积,您可以考虑 使用这个简单的表达式,而不是求助于通用方法。

【讨论】:

    【解决方案4】:

    看,妈,没有进口!

    >>> coeffs = [2., 4., 6.]
    >>> sum(coeff / (i+1) for i, coeff in enumerate(reversed(coeffs)))
    8.6666666666666661
    >>>
    

    我们的保证:适​​用于任何正数的多项式或退款!

    我们研究实验室的更新:保证延长; s/正/非负/ :-)

    更新这是工业级版本,在面对系数中的杂散整数时很稳健,没有循环中的函数调用,并且在设置:

    >>> icoeffs = [2, 4, 6]
    >>> tot = 0.0
    >>> divisor = float(len(icoeffs))
    >>> for coeff in icoeffs:
    ...     tot += coeff / divisor
    ...     divisor -= 1.0
    ...
    >>> tot
    8.6666666666666661
    >>>
    

    【讨论】:

    • +1,很好的解决方案(我敢肯定,与integ 实现的几乎相同)。如果我不在带有from __future__ import division 的文件中,我会将分母设为float(i + 1)
    【解决方案5】:

    如果从一开始就对二次或三次多项式进行积分,则导出显式积分表达式的另一种方法是使用辛普森规则;一个深刻的事实是,这种方法完全集成了 3 次及以下的多项式。

    借用 Mike Graham 的示例(我已经有一段时间没有使用 Python;如果代码看起来有问题,我们深表歉意):

    >>> import numpy
    >>> p = numpy.poly1d([2, 4, 6])
    >>> print p
       2
    2 x + 4 x + 6
    >>> integrand = (1 - 0)(p(0) + 4*p((0 + 1)/2) + p(1))/6
    

    使用辛普森法则计算integrand 的值。您可以自己验证该方法是否如宣传的那样有效。

    当然,我并没有简化integrand 的表达式来表示01 可以替换为任意值uv,并且代码仍然可以用于查找从uv的函数的积分。

    【讨论】:

    • 多么好的答案!辛普森的规则,经过验证,来自微积分。非常优雅,无论 Python 技能如何。
    猜你喜欢
    • 1970-01-01
    • 2019-08-04
    • 2013-12-21
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 2018-03-20
    • 2011-06-24
    相关资源
    最近更新 更多