更有效的积分循环

public double Integral(double[] x, double intPointOne, double intPointTwo) { double integral = 0; double i = intPointOne; do { integral += Function(x[i])*.001; i = i + .001; } while (i <= intPointTwo); return integral; } 

这是一个函数,我必须简单地使用部分的总和来集成x1-x2中的函数。 如何使这个循环更有效(使用更少的循环),但更准确?

Function在每次迭代中都会发生变化,但它应该是无关紧要的,因为它的数量级(或边界)应保持相对相同…

1)查看http://apps.nrbook.com/c/index.html的 4.3节,了解不同的算法。

2)要控制精度/速度因子,您可能需要指定边界x_lowx_high以及积分中所需的切片数量。 所以你的function看起来像这样

 // Integrate function f(x) using the trapezoidal rule between x=x_low..x_high double Integrate(Func f, double x_low, double x_high, int N_steps) { double h = (x_high-x_low)/N_steps; double res = (f(x_low)+f(x_high))/2; for(int i=1; i < N; i++) { res += f(x_low+i*h); } return h*res; } 

一旦理解了这种基本集成,就可以继续使用Numerical Recipies和其他资源中提到的更复杂的方案。

要使用此代码,请发出一个命令,如A = Integrate( Math.Sin, 0, Math.PI, 1440 );

这里通过方法计算积分:左手,梯形和中点

 ///  /// Return the integral from a to b of function f /// using the left hand rule ///  public static double IntegrateLeftHand(double a, double b, Func f, int strips = -1) { if (a >= b) return -1; // constraint: a must be greater than b // if strips is not provided, calculate it if (strips == -1) { strips = GetStrips(a, b, f); } double h = (b - a) / strips; double acc = 0.0; for (int i = 0; i < strips; i++) { acc += h * f(a + i * h); } return acc; } ///  /// Return the integral from a to b of function f /// using the midpoint rule ///  public static double IntegrateMidPoint(double a, double b, Func f, int strips = -1) { if (a >= b) return -1; // constraint: a must be greater than b // if strips is not provided, calculate it if (strips == -1) { strips = GetStrips(a, b, f); } double h = (b - a) / strips; double x = a + h / 2; double acc = 0.0; while (x < b) { acc += h * f(x); x += h; } return acc; } ///  /// Return the integral from a to b of function f /// using trapezoidal rule ///  public static double IntegrateTrapezoidal(double a, double b, Func f, int strips = -1) { if (a >= b) return -1; // constraint: a must be greater than b // if strips is not provided, calculate it if (strips == -1) { strips = GetStrips(a, b, f); } double h = (b - a) / strips; double acc = (h / 2) * (f(a) + f(b)); for (int i = 1; i < strips; i++) { acc += h * f(a + i * h); } return acc; } private static int GetStrips(double a, double b, Func f) { int strips = 100; for (int i = (int)a; i < b; i++) { strips = (strips > f(i)) ? strips : (int)f(i); } return strips; } Console.WriteLine("w/ strips:{0}", IntegrateLeftHand(0, 3.14, Math.Sin, 1440)); Console.WriteLine("without strips:{0}", IntegrateMidPoint(0, 30, x => x * x)); // or with a defined method for f(x) public static double myFunc(x) { return x * (x + 1); } Console.WriteLine("w/ strips:{0}", IntegrateLeftHand(0, 20, myFunc, 200)); 

如果您事先了解function,则可以分析它们,并查看哪些集成步骤大小适用于您的目的。 即线性function,您只需要一步,但对于其他function,您可能需要可变步骤。 至少看看你是否可以逃脱(pointTwo - pointOne)/1000.0

如果您需要通用function并且它不是功课,您应该强烈考虑现有的库或在您的第一年 – 第二年数学课程上刷新……

注意你的代码实际上有不使用i的错误(这是x的非常糟糕的名字):

 for(x=intPointOne; x<=intPointTwo;x+=0.001) { integral += Function(x)*.001; } 

您正在使用左手规则进行整合。 只要函数在域中具有正斜率和负斜率(由于使用左端点的错误抵消),这仅是半精确的。

我建议,至少,移动到梯形规则(计算由集合形成的梯形下的面积(x [i],0),(x [i + 0.001],0),(x [i],函数(x [i]),(x [i + 0.001],函数(x [x + 0.001])。

更好的解决方案是使用辛普森的规则。 这是一个较慢的算法,但准确性应该允许您显着增加您的间隔。

请看这里: 数值整合的细节。