【问题标题】:Trapezoid Rule in C, wrong answerC中的梯形规则,错误答案
【发布时间】:2018-06-29 14:56:55
【问题描述】:

我想在 C 中为一个项目实现梯形图。我正在使用书中Numerical Recipes in C 第137 页中的一个示例。我首先只是想复制代码,尝试使用它来实现不同的功能,然后再尝试理解每一行。但是,我的程序没有输出正确的答案:

#include <stdio.h>
#include <math.h>
float h(float x)
{ 
    return sin(x);
}
float trapzd(float (*func)(float), float a, float b, int n)
{   float x, tnm, sum, del; 
    static float s;
    int it, j;
    if (n == 1) {
        return (s=0.5*(b-a)*(h(a)+h(b)));


    } 
    else
    {
        for (it=1,j=1;j<n-1;j++) it <<=1;
        tnm=it;
        del=(b-a)/tnm;
        x=a+0.5*del;
        for(sum=0.0,j=1; j<=it; j++, x+=del) sum+=h(x);
        s=0.5*(s+(b-a)*sum/tnm);   

        return s;
    }

}
int main(void)
{   
    for (int i = 1; i <= 10; ++i)
    {
    printf("With n = %d, the approximation is %g.\n", i, trapzd(h,0,1,i));
    }

}

所以我想将sin(x)0 整合到1,这应该等于0.45,但程序输出0.000002。如果我使用exp(x),则输出是0.50000,而不是大约1.7。为什么这不起作用?

【问题讨论】:

  • 是的,我在这里复制并调整了节奏。编辑:我刚刚改变了它,它现在至少输出 0.229,一个更好的价值! Edit2:另外,如果我将步数(变量 n)增加到 100,它会输出 -nan。
  • 啊,是的,现在它输出了正确的结果。看来是书上的错误了。不过,如果我将步数增加到 100,我不明白为什么它会输出 -nan

标签: c numerical-integration


【解决方案1】:

例程trapzd 旨在被迭代调用以接近正确答案。对于参数n,您不能直接使用 20 调用它。你必须先用 1 调用它,然后是 2,然后是 3,以此类推。

例如,使用 Numerical Recipes 中的原始代码(删除您在 trapzd 中插入的 printf 语句):

for (int i = 1; i <= 20; ++i)
    printf("With n = %d, the approximation is %g.\n", i, trapzd(h, 0, 1, i));

另外,正如Mark Dickinson 所指出的,x=+del 应该是x+=del

Numerical Recipes 的来源是可怕的 设计。该函数具有内部状态,在静态对象s 中。也许有一些教学上的借口,但这样的代码应该永远在现实世界的代码中使用。 (实现进行迭代细化的例程的适当方法是将状态信息返回给调用者,它们可以在未来的调用中传回。)

调用函数的说明在您引用的参考文献中:

当以 n=1 调用时,例程返回来自 a 的 [f(x) dx 的积分的最粗略估计到b]。后续调用 n=2,3,... a(按该顺序)将通过添加 2n-2 个额外的内部点来提高准确性。

不要在不懂的情况下盲目复制源代码。

【讨论】:

  • 谢谢。迭代调用是什么意思?可以发个例子吗?
  • @Eren:在这种情况下,迭代是指首先trapzd(h, 0, 1, 1)调用函数,然后用trapzd(h, 0, 1, 2),然后trapzd(h, 0, 1, 3),......你不能简单地调用它有 20 个;你必须逐步到达那里。我添加了代码来证明这一点。
  • 您好,再次非常感谢您。我现在明白这意味着什么,但如果我这样做,输出就会增加。例如,对于 i wolframalpha.com/input/?i=integral+sin(x)+from+0+to+1) 左右的“真实”值吗?
  • 我将上面的代码编辑为我现在使用的代码。我删除了 trapzd 中的 printf 语句,并插入了 for 循环 int main(void) 而不是 x=+del 我将其更正为 x+=del
  • @Eren:当我编译并执行该代码时,最后一行是“当 n = 10 时,近似值为 0.459697。”这似乎是理想的行为。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多