我正在尝试使用梯形法则集成函数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);
}
答案 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。可以使用以下链接找到完全积分:
#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;
}