/*
* 計算數值積分的類 Integral
*
* 周長發編制
*/
using System;
namespace MSAlgorithm
{
public abstract class Integral
{
/// <summary>
/// 抽象函數:計算積分函數值,必須在派生類中覆蓋該函數
/// </summary>
/// <param name="x">函數變量</param>
/// <returns>double型,對應的函數值</returns>
public abstract double Func(double x);
/// <summary>
/// 基本構造函數
/// </summary>
public Integral()
{ }
/// <summary>
/// 變步長梯形求積法
/// 調用時,須覆蓋計算函數f(x)值的虛函數double Func(double x)
/// </summary>
/// <param name="a">積分下限</param>
/// <param name="b">積分上限,要求b>a</param>
/// <param name="eps">積分精度要求</param>
/// <returns>double 型,積分值</returns>
public double GetValueTrapezia(double a, double b, double eps)
{
int n, k;
double fa, fb, h, t1, p, s, x, t = 0;
//積分區間端點的函數值
fa = Func(a);
fb = Func(b);
//迭代初值
n = 1;
h = b - a;
t1 = h * (fa + fb) / 2.0;
p = eps + 1.0;
//迭代計算
while (p >= eps)
{
s = 0.0;
for (k = 0; k <= n - 1; k++)
{
x = a + (k + 0.5) * h;
s = s + Func(x);
}
t = (t1 + h * s) / 2.0;
p = Math.Abs(t1 - t);
t1 = t;
n = n + n;
h = h / 2.0;
}
return (t);
}
/// <summary>
/// 變步長辛卜生求積法
/// 調用時,須覆蓋計算函數f(x)值的虛函數double Func(double x)
/// </summary>
/// <param name="a">積分下限</param>
/// <param name="b">積分上限,要求b>a</param>
/// <param name="eps">積分精度要求</param>
/// <returns>double 型,積分值</returns>
public double GetValueSimpson(double a, double b, double eps)
{
int n, k;
double h, t1, t2, s1, s2 = 0, ep, p, x;
//計算初值
n = 1;
h = b - a;
t1 = h * (Func(a) + Func(b)) / 2.0;
s1 = t1;
ep = eps + 1.0;
//迭代計算
while (ep >= eps)
{
p = 0.0;
for (k = 0; k <= n - 1; k++)
{
x = a + (k + 0.5) * h;
p = p + Func(x);
}
t2 = (t1 + h * p) / 2.0;
s2 = (4.0 * t2 - t1) / 3.0;
ep = Math.Abs(s2 - s1);
t1 = t2;
s1 = s2;
n = n + n;
h = h / 2.0;
}
return (s2);
}
/// <summary>
/// 自適應梯形求積法
/// 調用時,須覆蓋計算函數f(x)值的虛函數double Func(double x)
/// </summary>
/// <param name="a">積分下限</param>
/// <param name="b">積分上限,要求b>a</param>
/// <param name="d">對積分區間進行分割的最小步長,當子區間的寬度,小於d時,即使沒有滿足精度要求,也不再往下進行分割</param>
/// <param name="eps">積分精度要求</param>
/// <returns>double 型,積分值</returns>
public double GetValueATrapezia(double a, double b, double d, double eps)
{
double h, f0, f1, t0, z;
double[] t = new double[2];
//迭代初值
h = b - a;
t[0] = 0.0;
f0 = Func(a);
f1 = Func(b);
t0 = h * (f0 + f1) / 2.0;
//遞歸計算
ppp(a, b, h, f0, f1, t0, eps, d, t);
z = t[0];
return (z);
}
/// <summary>
/// 內部函數
/// </summary>
/// <param name="x0"></param>
/// <param name="x1"></param>
/// <param name="h"></param>
/// <param name="f0"></param>
/// <param name="f1"></param>
/// <param name="t0"></param>
/// <param name="eps"></param>
/// <param name="d"></param>
/// <param name="t"></param>
private void ppp(double x0, double x1, double h, double f0, double f1, double t0, double eps, double d, double[] t)
{
double x, f, t1, t2, p, g, eps1;
x = x0 + h / 2.0;
f = Func(x);
t1 = h * (f0 + f) / 4.0;
t2 = h * (f + f1) / 4.0;
p = Math.Abs(t0 - (t1 + t2));
if ((p < eps) || (h / 2.0 < d))
{
t[0] = t[0] + (t1 + t2);
return;
}
else
{
g = h / 2.0;
eps1 = eps / 1.4;
//遞歸
ppp(x0, x, g, f0, f, t1, eps1, d, t);
ppp(x, x1, g, f, f1, t2, eps1, d, t);
return;
}
}
/// <summary>
/// 龍貝格求積法
/// 調用時,須覆蓋計算函數f(x)值的虛函數double Func(double x)
/// </summary>
/// <param name="a">積分下限</param>
/// <param name="b">積分上限,要求b>a</param>
/// <param name="eps">積分精度要求</param>
/// <returns>double 型,積分值</returns>
public double GetValueRomberg(double a, double b, double eps)
{
int m, n, i, k;
double h, ep, p, x, s, q = 0;
double[] y = new double[10];
//迭代初值
h = b - a;
y[0] = h * (Func(a) + Func(b)) / 2.0;
m = 1;
n = 1;
ep = eps + 1.0;
//迭代計算
while ((ep >= eps) && (m <= 9))
{
p = 0.0;
for (i = 0; i < n - 1; i++)
{
x = a + (i + 0.5) * h;
p = p + Func(x);
}
p = (y[0] + h * p) / 2.0;
s = 1.0;
for (k = 1; k <= m; k++)
{
s = 4.0 * s;
q = (s * p - y[k - 1]) / (s - 1.0);
y[k - 1] = p;
p = q;
}
ep = Math.Abs(q - y[m - 1]);
m = m + 1;
y[m - 1] = q;
n = n + n;
h = h / 2.0;
}
return (q);
}
/// <summary>
/// 計算一維積分的連分式法
/// 調用時,須覆蓋計算函數f(x)值的虛函數double Func(double x)
/// </summary>
/// <param name="a">積分下限</param>
/// <param name="b">積分上限,要求b>a</param>
/// <param name="eps">積分精度要求</param>
/// <returns>double 型,積分值</returns>
public double GetValuePq(double a, double b, double eps)
{
int m, n, k, l, j;
double hh, t1, s1, ep, s, x, t2, g = 0;
double[] h = new double[10];
double[] bb = new double[10];
//迭代初值
m = 1;
n = 1;
hh = b - a;
h[0] = hh;
t1 = hh * (Func(a) + Func(b)) / 2.0;
s1 = t1;
bb[0] = s1;
ep = 1.0 + eps;
//迭代計算
while ((ep >= eps) && (m <= 9))
{
s = 0.0;
for (k = 0; k <= n - 1; k++)
{
x = a + (k + 0.5) * hh;
s = s + Func(x);
}
t2 = (t1 + hh * s) / 2.0;
m = m + 1;
h[m - 1] = h[m - 2] / 2.0;
g = t2;
l = 0;
j = 2;
while ((l == 0) && (j <= m))
{
s = g - bb[j - 2];
if (Math.Abs(s) + 1.0 == 1.0)
l = 1;
else
g = (h[m - 1] - h[j - 2]) / s;
j = j + 1;
}
bb[m - 1] = g;
if (l != 0)
bb[m - 1] = 1.0e+35;
g = bb[m - 1];
for (j = m; j >= 2; j--)
g = bb[j - 2] - h[j - 2] / g;
ep = Math.Abs(g - s1);
s1 = g;
t1 = t2;
hh = hh / 2.0;
n = n + n;
}
return (g);
}
/// <summary>
/// 高振盪函數求積法
/// 調用時,須覆蓋計算函數f(x)值的虛函數double Func(double x)
/// </summary>
/// <param name="a">積分下限</param>
/// <param name="b">積分上限,要求b>a</param>
/// <param name="m">被積函數中振盪函數的角頻率</param>
/// <param name="n">給定積分區間兩端點上的導數最高階數+1</param>
/// <param name="fa">一維數組,長度爲n,存放f(x)在積分區間端點x=a處的各階導數值<param>
/// <param name="fb">一維數組,長度爲n,存放f(x)在積分區間端點x=b處的各階導數值</param>
/// <param name="s">一維數組,長度爲2,其中s(1)返回f(x)cos(mx)在積分區間的積分值,
/// s(2) 返回f(x)sin(mx)在積分區間的積分值</param>
/// <returns>double 型,積分值</returns>
public double GetValuePart(double a, double b, int m, int n, double[] fa, double[] fb, double[] s)
{
int mm, k, j;
double sma, smb, cma, cmb;
double[] sa = new double[4];
double[] sb = new double[4];
double[] ca = new double[4];
double[] cb = new double[4];
//三角函數值
sma = Math.Sin(m * a);
smb = Math.Sin(m * b);
cma = Math.Cos(m * a);
cmb = Math.Cos(m * b);
//迭代初值
sa[0] = sma;
sa[1] = cma;
sa[2] = -sma;
sa[3] = -cma;
sb[0] = smb;
sb[1] = cmb;
sb[2] = -smb;
sb[3] = -cmb;
ca[0] = cma;
ca[1] = -sma;
ca[2] = -cma;
ca[3] = sma;
cb[0] = cmb;
cb[1] = -smb;
cb[2] = -cmb;
cb[3] = smb;
s[0] = 0.0;
s[1] = 0.0;
mm = 1;
//循環迭代
for (k = 0; k <= n - 1; k++)
{
j = k;
while (j >= 4)
j = j - 4;
mm = mm * m;
s[0] = s[0] + (fb[k] * sb[j] - fa[k] * sa[j]) / (1.0 * mm);
s[1] = s[1] + (fb[k] * cb[j] - fa[k] * ca[j]) / (1.0 * mm);
}
s[1] = -s[1];
return s[0];
}
/// <summary>
/// 勒讓德-高斯求積法
/// 調用時,須覆蓋計算函數f(x)值的虛函數double Func(double x)
/// </summary>
/// <param name="a">積分下限</param>
/// <param name="b">積分上限,要求b>a</param>
/// <param name="eps">積分精度要求</param>
/// <returns>double 型,積分值</returns>
public double GetValueLegdGauss(double a, double b, double eps)
{
int m, i, j;
double s, p, ep, h, aa, bb, w, x, g = 0;
//勒讓德-高斯求積係數
double[] t ={-0.9061798459,-0.5384693101,0.0,
0.5384693101,0.9061798459};
double[] c ={0.2369268851,0.4786286705,0.5688888889,
0.4786286705,0.2369268851};
//迭代初值
m = 1;
h = b - a;
s = Math.Abs(0.001 * h);
p = 1.0e+35;
ep = eps + 1.0;
//迭代計算
while ((ep >= eps) && (Math.Abs(h) > s))
{
g = 0.0;
for (i = 1; i <= m; i++)
{
aa = a + (i - 1.0) * h;
bb = a + i * h;
w = 0.0;
for (j = 0; j <= 4; j++)
{
x = ((bb - aa) * t[j] + (bb + aa)) / 2.0;
w = w + Func(x) * c[j];
}
g = g + w;
}
g = g * h / 2.0;
ep = Math.Abs(g - p) / (1.0 + Math.Abs(g));
p = g;
m = m + 1;
h = (b - a) / m;
}
return (g);
}
/// <summary>
/// 拉蓋爾-高斯求積法
/// 調用時,須覆蓋計算函數f(x)值的虛函數double Func(double x)
/// </summary>
/// <returns>double 型,積分值</returns>
public double GetValueLgreGauss()
{
int i;
double x, g;
//拉蓋爾-高斯求積係數
double[] t = { 0.26355990, 1.41340290, 3.59642600, 7.08580990, 12.64080000 };
double[] c = { 0.6790941054, 1.638487956, 2.769426772, 4.315944000, 7.104896230 };
//循環計算
g = 0.0;
for (i = 0; i <= 4; i++)
{
x = t[i];
g = g + c[i] * Func(x);
}
return (g);
}
/// <summary>
/// 埃爾米特-高斯求積法
/// 調用時,須覆蓋計算函數f(x)值的虛函數double Func(double x)
/// </summary>
/// <returns>double 型,積分值</returns>
public double GetValueHermiteGauss()
{
int i;
double x, g;
//埃爾米特-高斯求積係數
double[] t = { -2.02018200, -0.95857190, 0.0, 0.95857190, 2.02018200 };
double[] c = { 1.181469599, 0.9865791417, 0.9453089237, 0.9865791417, 1.181469599 };
//循環計算
g = 0.0;
for (i = 0; i <= 4; i++)
{
x = t[i];
g = g + c[i] * Func(x);
}
return (g);
}
}
}
注:本代碼爲原作者所有,本人只是摘錄,如有侵犯作者,請與本人聯繫
Email:[email protected]