重新审视抛物线下的面积

2 投票
2 回答
1234 浏览
提问于 2025-04-16 08:42

我之前无法从之前的问题中找到答案,因为我不是这个网站的会员,所以回来的时候无法评论。现在我有个问题:

为了找出被图形y=x^2和x轴围起来的区域在[a,b]区间内的面积,我们可以通过画一些“薄薄的”矩形来近似这个区域,然后把这些矩形的面积加起来。我们可以把区间[a,b]分成n个宽度相同的小区间,宽度h=(b-a)/n。在每个小区间里,我们可以画一个矩形,矩形的高度y=r,其中r是这个小区间在x轴上的中间值。这个矩形的面积就是h乘以y。请写一个Python函数,接受a、b和n作为参数,并使用上述方法返回在抛物线y=x^2下的近似面积。如果你能解释一下你的程序为什么能这样工作,那就太好了。

感谢热心的成员,我找到了以下程序(请编辑这个程序,因为我不知道怎么做)

def parabola(x):
    y = x*x
    return y

def approx_area(fn, a, b, n):
    """
    Approximate the area under fn in the interval [a,b]
    by adding the area of n rectangular slices.
    """

    a = float(a)
    b = float(b)
    area = 0.0
    for slice in range(n):
        left = a + (b-a)*slice/n
        right = a + (b-a)*(slice+1)/n
        mid = (left + right)*0.5
        height = fn(mid)
        width = right - left
        area += height * width

    return area

    print "Area is", approx_area(parabola, -1.0, 1.0, 500)

不过,我需要把这个放在一个完整的函数里。你有什么想法吗?

2 个回答

1

这里有一个不错的可视化效果,可以在 这个链接 找到。

我们来看一下抛物线在a和b之间的部分,然后把它分成一系列垂直的矩形切片,每个矩形的顶部正好在抛物线上。

这样,每个矩形的一角就会“悬空”在抛物线的上面,而另一角则太低,留下了未填充的空间。因此,抛物线下的面积等于矩形的面积,加上一点,再减去一点。但是,我们怎么比较这些小部分呢?矩形的面积是多了一点,还是少了一点呢?

alt text

如果我们在矩形的顶部中心画一条切线,就可以“切掉”重叠的部分,把它翻过来,放到另一边;注意,这样做并不会改变矩形的总面积(现在变成了一个梯形)。

alt text alt text

现在我们可以看到,在抛物线的两侧还有一点空间,所以梯形的面积稍微小于抛物线下的面积。我们可以把梯形的顶部看作是在抛物线底部形成的一系列直线段(这叫做“线性分段近似”);而这些线段下的面积几乎和我们想要的实际面积相同,但总是稍微少一点。

那么,我们怎么才能把这个“稍微少一点”的量减到最小,以使我们计算的面积更准确呢?一种方法是使用曲线近似,而不是直线;这就引出了样条曲线(比如贝塞尔曲线、NURBS等)。另一种方法是使用更多的短线段,以“提高分辨率”。微积分把这个想法推向极限(有双关的意思),使用无限多个无限短的线段。

3

好吧,通过把函数改成 y = x 并尝试一些已知的输入值,我得出结论,它运行得很好:

0 .. 1 =>  0.5
0 .. 2 =>  2.0
1 .. 2 =>  1.5
0 .. 9 => 40.5

如果你想把所有内容放在一个函数里,只需去掉 parabola(),把 approx_area() 函数的第一个参数(和调用)去掉,然后把:

height = fn(mid)

改成:

height = mid * mid

就像这样:

def approx_area(a, b, n):
    """
    Approximate the area under fn in the interval [a,b]
    by adding the area of n rectangular slices.
    """

    a = float(a)
    b = float(b)
    area = 0.0
    for slice in range(n):
        left = a + (b-a)*slice/n
        right = a + (b-a)*(slice+1)/n
        mid = (left + right)*0.5
        height = mid * mid
        width = right - left
        area += height * width

    return area

print "Area is", approx_area(-1, 1, 500)

请注意,我通常不会给作业提供这么多明确的帮助,但因为你已经完成了大部分工作,所以这只是一个小小的推动,帮助你完成。

建议你不要直接提交这段代码,因为简单的网络搜索就能轻易找到它,这样可能会影响你的成绩。

仔细研究它,彻底理解它是怎么工作的,然后尝试自己重新编码,而不是直接抄袭。相信我,这对你的职业生涯帮助会更大。


为了让你理解这个方法背后的理论,考虑一下函数 y = x 的一部分:

7   .
6  /|
5 / |
  | |
  | |
  | |
  | |
  | |
0 +-+
  567

顶部的中点 y 坐标(也是高度)是 (5 + 7) / 2,也就是 6,宽度是 2,所以面积是 12

现在,这实际上是真实的面积,但这只是因为我们使用的公式。对于非线性公式,由于“线”的顶部的特性,会有一些不准确性。具体来说,在你的例子中,抛物线是弯曲的。

但是,随着你使用越来越薄的切片,这些不准确性会越来越小,因为任何线在缩短时都会趋向于一条直线(线性)。对于上面的例子,如果你把它分成两个切片,面积将是 5.5 x 16.5 x 1,总共 12。如果你的线不是直的,两个切片的结果会比一个切片的结果更接近真实值。

对于你的抛物线(但为了让我更简单,从 x = 0 .. 1 开始,只需把所有值翻倍到 x = -1 .. 1,因为它在 y 轴周围是对称的),在一个切片的情况下,最糟糕的情况是中点在 x = 0.5, y = 0.25,当你把这个 y 乘以宽度 1 时,得到的面积是 0.25

用两个切片(宽度 = 0.5),中点在:

   x       y    y x width
----  ------    ---------
0.25  0.0625      0.03125
0.75  0.5625      0.28125
                ---------
                  0.31250

所以那里的面积估计是 0.3125

用四个切片(宽度 = 0.25),中点在:

    x         y   y x width
-----  --------  ----------
0.125  0.015625  0.00390625
0.375  0.140625  0.03515625
0.625  0.390625  0.09765625
0.875  0.765625  0.19140625
                 ----------
                 0.32812500

所以那里的面积估计是 0.328125

用八个切片(宽度 = 0.125),中点在:

     x           y    y x width
------  ----------  -----------
0.0625  0.00390625  0.000488281
0.1875  0.03515625  0.004394531
0.3125  0.09765625  0.012207031
0.4375  0.19140625  0.023925781
0.5625  0.31640625  0.039550781
0.6875  0.47265625  0.059082031
0.8125  0.66015625  0.082519531
0.9375  0.87890625  0.109863281
                    -----------
                    0.332031248

所以那里的面积估计是 0.332031248

正如你所看到的,这个值越来越接近真实的面积 1/3(我知道这一点,因为我懂微积分,见下文)。

希望这能帮助你理解你手上的代码。


如果你真的想知道这个是怎么工作的,你需要了解微积分,特别是积分和导数。这些方法可以将一个公式转化为另一个公式,用于计算线的斜率和线下的面积。

但是,除非你会经常使用它并需要真正的(数学上的)准确性,否则你可能只需使用你正在学习的近似方法。

撰写回答