精确积分循环的结束条件

时间:2015-03-17 18:06:55

标签: c while-loop

我正在尝试使用梯形法则集成函数1 /((1 + x ^ 2)x ^ 0.5)。我需要尽可能精确的精度所以我因此增加了条带的数量N,直到计算机无法识别连续N的总数之间的变化。但是,结束条件当前不起作用,导致持续集成。有没有人比我现在的代码有更好的建议?

非常感谢, 贝丝

#include<stdio.h>
#include<math.h>
#include<float.h>

double inter(double x, double h, double y, double N, double total) 
{

        total= total +0.5*(1/((1+pow(x,2))*sqrt(x)));

        x=x+h;

        while (x<y)
        {
            total=total+(1/((1+pow(x,2))*sqrt(x)));

            x=x+h;

            //printf("x - %.16lf \n", x);
        }
        total= total +0.5*(1/((1+pow(x,2))*sqrt(x)));
    total=total*h;
    //printf("t - %lf \n", total);
    return total;
    }
main()

{   
double x,y,total,h,value,newvalue,f, N;
int finish;
x=0.1;
    y=1000;
    total=0;
    N=1000;
finish=0;
value=0;

while(finish==0)
{   
    h=(y-x)/(N-1); 

    newvalue=inter(x,h,y,N,total);
    printf("h-%.16lf\n", h);
    printf("N-%.16lf\n", N);
    printf("New value %.16lf\n", newvalue);
    printf("c-%.16lf\n", value);
    if(value==newvalue)
    {
        finish=1;   
        printf("finish-%d\n", finish);
    }
    else
        {
            value=newvalue;
            newvalue=newvalue-3;
            N=N+1000;
            printf("newvalue-%lf\n", newvalue);
            printf("value-%lf\n", value);
        }



}
printf("%lf\n", value);
}

2 个答案:

答案 0 :(得分:3)

如果您希望创建数值积分的自动细化,一种方法是查看积分的相对收敛。

double previous = 0;
double current = inter( x, (y-x)/(N-1), y, N, total ); // Solve some baseline
do
{
    N = N + 1000;
    h = (y-x)/(N-1);
    previous = current;
    current = inter( x, h, y, N, total );
} while( abs( current - previous ) / current > 0.001 );

在您的估算中观察到相对细化程度低于0.1%后,该代码将停止。减少0.001将有效提高您的准确性。通常,比较双打的最佳方法是通过公差检查,如:

abs( a - b ) < k

其中k是您希望达到的准确度的一个因素。

答案 1 :(得分:1)

这个积分很难,因为f(x) - > ∞为x - >在这个例子中,我将范围更改为1到1000.我还使用求和函数来最小化求和大量值时的舍入误差。来自wolframalpha~ = .487474的积分,该程序导致〜= .487475。可以使用以下链接找到完全积分:

integral 1/((1+x^2)sqrt(x))

#include<stdio.h>
#include<math.h>
#include<float.h>

/* clear array */
void clearsum(double asum[2048])
{
size_t i;
    for(i = 0; i < 2048; i++)
        asum[i] = 0.;
}

/* add a number into array */
void addtosum(double d, double asum[2048])
{
size_t i;
    while(1){
        /* i = exponent of d */
        i = ((size_t)((*(unsigned long long *)&d)>>52))&0x7ff;
        if(i == 0x7ff){         /* max exponent, could be overflow */
            asum[i] += d;
            return;
        }
        if(asum[i] == 0.){      /* if empty slot store d */
            asum[i] = d;
            return;
        }
        d += asum[i];           /* else add slot to d, clear slot */
        asum[i] = 0.;           /* and continue until empty slot */
    }
}

/* return sum from array */
double returnsum(double asum[2048])
{
double sum = 0.;
size_t i;
    for(i = 0; i < 2048; i++)
        sum += asum[i];
    return sum;
}

double fx(double x)
{
    return 1./((1.+x*x)*sqrt(x));
}

double inter(double x, double y, double n) 
{
double asum[2048];              /* for summation functions */
double h;
double d;
    if(n < 1.){
        n = 1.;
        h = 0.;
    } else {
        h = (y-x)/(n-1.0);
    }
    y -= h/2.;
    clearsum(asum);
    d = .5*h*fx(x);
    addtosum(d, asum);
    for( ; x < y; x += h){
        d = h*fx(x);
        addtosum(d, asum);
    }
    d = .5*h*fx(x);
    addtosum(d, asum);
    d = returnsum(asum);
    return d;
}

int main()
{   
double x,y,n,value,newvalue;
    x=1.0;
    y=1000.;
    value=0.;

    for(n = 100000000.; 1; n += 100000000.)
    {   
        newvalue=inter(x,y,n);
        printf("new value %.16lf %.0lf\n", newvalue, n);
        if(fabs(newvalue-value) < (newvalue*1E-7))
            break;
        value = newvalue;
    }
    return 0;
}

使用Simpson的规则,结果更准确,并且收敛于更小的n值:

#include<stdio.h>
#include<math.h>
#include<float.h>

/* clear array */
void clearsum(double asum[2048])
{
size_t i;
    for(i = 0; i < 2048; i++)
        asum[i] = 0.;
}

/* add a number into array */
void addtosum(double d, double asum[2048])
{
size_t i;
    while(1){
        /* i = exponent of d */
        i = ((size_t)((*(unsigned long long *)&d)>>52))&0x7ff;
        if(i == 0x7ff){         /* max exponent, could be overflow */
            asum[i] += d;
            return;
        }
        if(asum[i] == 0.){      /* if empty slot store d */
            asum[i] = d;
            return;
        }
        d += asum[i];           /* else add slot to d, clear slot */
        asum[i] = 0.;           /* and continue until empty slot */
    }
}

/* return sum from array */
double returnsum(double asum[2048])
{
double sum = 0.;
size_t i;
    for(i = 0; i < 2048; i++)
        sum += asum[i];
    return sum;
}

double fx(double x)
{
    return 1./((1.+x*x)*sqrt(x));
}

double simpson(double x, double y, double n) 
{
double asum[2048];              /* for summation functions */
double h;
double a;
    if(n < 1.){
        n = 1.;
        h = 0.;
    } else {
        h = (y-x)/(n-1.0);
    }
    y += h/2.;
    clearsum(asum);
    for( ; x < y; x += h){
        a = h/6.*(fx(x) + 4.*fx(x + h/2.) + fx(x + h));
        addtosum(a, asum);
    }
    a = returnsum(asum);
    return a;
}

int main()
{   
double x,y,n,value,newvalue;
    x=1.0;
    y=1000.;
    value=0.;

    for(n = 1000.; 1; n += 1000.)
    {   
        newvalue=simpson(x,y,n);
        printf("new value %.16lf %.0lf\n", newvalue, n);
        if(fabs(newvalue-value) < (newvalue*1E-10))
            break;
        value = newvalue;
    }
    return 0;
}