问题描述
我正在尝试使用此公式在n个间隔内实施Boole规则
I am attempting to implement Boole's rule over n intervals using this formula
到目前为止,我已经开发了以下代码:
So far I have developed this code:
//f = function on the range [a,b] n = number of intervals
long double booles(long double (*f) (long double),
double a, double b, int n)
{
long double sum=7*f(a); //because the starting value is not doubled
long double h = (b - a)/(n-1); //width of each interval
int mod;
int i =1;
while (i<n-1)
{
mod = i%4;
if (mod==0)
sum+=14*f(a+i*h);
else if (mod==1)
sum+=32*f(a+i*h);
else if (mod==2)
sum+=12*f(a+i*h);
else
sum+=32*f(a+i*h);
++i;
}
return 2* h/45 * sum;
}
这将运行并给出正确的答案,但它不在Bool错误规则之内,该错误指出错误为.我已经解决了将第一项加倍的问题,但是我不确定如何在循环快结束时解决可能的加倍问题.而且,该误差相对较大,以至于我认为我唯一的问题不是最后四个术语.
This will run and give a decent answer but it not within the rules for Bool's error which states that the error is .I fixed the problem with doubling the first term but I am not sure how to fix the possible doubling near the end of the loop. Also, the error is relatively large enough that I don't think that my only problem is the last four terms.
推荐答案
-
长双
Wiki说::扩展精度浮点类型.未指定实际属性.与float和double类型不同,如果提供了更高的精度格式,则可以是80位浮点格式,非IEEE"double-double"或IEEE 754四精度浮点格式,否则为双倍的.有关详细信息,请参见关于long double的文章.
Wiki says: extended precision floating-point type. Actual properties unspecified. Unlike types float and double, it can be either 80-bit floating point format, the non-IEEE "double-double" or IEEE 754 quadruple-precision floating-point format if a higher precision format is provided, otherwise it is the same as double. See the article on long double for details.
- 因此很难说出您实际使用的数据类型(我更喜欢使用双精度数据)
常数
您将整数和浮点数混合在一起,因此编译器必须决定使用什么.将所有浮点数以 45
重写为 45.0
以确保正确完成,或者将 a + i * h
... i
是int而 h
是double ...
you are mixing integer and floating numbers together so the compiler has to decide what to use. Rewrite all floating numbers as 45
to 45.0
to be sure it is done correctly or a+i*h
... the i
is int and h
is double ...
集成
不知道值的总和和范围的大小,但是要提高浮动精度,您应该避免将大小值相加,因为如果指数差异太大,则会失去太多相关性尾数位.
do not know the magnitude of the sum and range of your values but to improve floating precision you should avoid adding big and small values together because if the exponents are too different you loose too much of relevant mantissa bits.
两个变量的总和也是如此(在C ++中):
So do the sum in two variables something like this (in C++):
double suml=0.0,sumh=0.0,summ=1000.0;
for (int i=0;i<n;i++)
{
suml+=...; // here goes the formula
if (fabs(suml)>summ) { sumh+=suml; suml=0; }
} sumh+=suml; suml=0;
// here the result is in sumh
-
summ
是suml的最大幅度.与您的求和迭代值相比,该值应该在相对安全的范围内,例如,100-10000
比平均值大一倍.summ
is max magnitude of suml. It should be in relatively safe range in comparison to your sum iteration value for example100-10000
times bigger then average value.suml
是低强度和变量如果求和值的范围确实很大,则可以添加另一个,如果
if the range of your summed values is really big then you can add another if
if (fabs(value)>summ) sumh+=value; else suml+=value;
如果它更大,那么您可以用相同的方式求和任意数量的变量,只需将值的范围除以某种意义上的全部范围即可.
if it is even much bigger then you can sum into any count of variables in the same manner just divide the range of value to some meaning full ranges
公式
可能是我遗漏了一些东西,但是为什么要修改呢?如我所见,您根本不需要循环,而且if已经过时了,那么为什么要使用
a + i * h
而不是a + = h
?可以提高性能和精度may be I am missing something but why are you mod-ing? As I see it you do not need the loop at all and also the ifs are obsolete so why to use
a+i*h
and nota+=h
? it would improve performance and precision类似这样的东西:
double sum,h; h = (b-a)/double(n-1); sum = 7.0*f(a); a+=h; sum+=32.0*f(a); a+=h; sum+=12.0*f(a); a+=h; sum+=32.0*f(a); a+=h; sum+= 7.0*f(a); a+=h; return 2.0*h*sum/45.0; // + the thing in the bullet 3 of coarse ... // now I see you had an error in your constants !!!
[edit1]部门已实施(未翻两番)
//--------------------------------------------------------------------------- double f(double x) { // return x+0.2*x*x-0.001*x*x*x+2.0*cos(0.1*x)*tan(0.01*x*x)+25.0; return x+0.2*x*x-0.001*x*x*x; } //--------------------------------------------------------------------------- double integrate_rect(double (*f)(double),double x0,double x1,int n) { int i; double s=0.0,x=x0,dx=(x1-x0)/double(n-1); for (i=0;i<n;i++,x+=dx) s+=f(x); return s*dx; } //--------------------------------------------------------------------------- double integrate_Boole(double (*f)(double),double x0,double x1,int n) { n-=n%5; if (n<5) n=5; int i; double s=0.0,x=x0,dx=(x1-x0)/double(n-1); for (i=0;i<n;i+=5) { s+= 7.0*f(x); x+=dx; s+=32.0*f(x); x+=dx; s+=12.0*f(x); x+=dx; s+=32.0*f(x); x+=dx; s+= 7.0*f(x); x+=dx; } s*=(2.0*dx)/(45.0); return s*1.25; // this is the ratio to cover most cases } //--------------------------------------------------------------------------- void main() { int n=100000; double x0=0.0,x1=+100.0,i0,i1; i0=integrate_rect (f,x0,x1,n); cout << i0 << endl; i1=integrate_Boole(f,x0,x1,n); cout << i1 << endl << i0/i1; } //---------------------------------------------------------------------------
我主要使用矩形尺,因为在 FPU 上,这是最快,最精确的方法.更高级的方法在纸张上会更好,但在计算机上,额外的开销和舍入通常较慢/较不精确,而与矩形尺相同的精度
I use mostly rectangular rule because on FPU is the quickest and most precise way. The more advanced approaches are better on paper but on computer the added overhead and rounding is usually slower/less precise then the same accuracy with rectangular rule
这篇关于N个间隔的布尔定律(C)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!