算法对序列的收敛加速。初始化方式使用参数nmax调用构造函数,nmax是要求和的项数,以及eps,即所需的精度。然后连续调用next函数,参数为next部分和序列的。序列极限的当前估计值为next返回。检测到收敛设置标志cnvgd。
using System;
namespace Legalsoft.Truffer
{
/// <summary>
/// Convergence acceleration of a sequence by the algorithm.Initialize by
/// calling the constructor with arguments nmax, an upper bound on the
/// number of terms to be summed, and epss, the desired accuracy.Then make
/// successive calls to the function next, with argument the next partial sum
/// of the sequence. The current estimate of the limit of the sequence is
/// returned by next.The flag cnvgd is set when convergence is detected.
/// </summary>
public class Epsalg
{
private double[] e { get; set; }
private int n { get; set; }
private int ncv { get; set; }
public bool cnvgd { get; set; }
/// <summary>
/// Numbers near machine underflow and overflow limits.
/// </summary>
private double eps { get; set; }
private double small { get; set; }
private double big { get; set; }
private double lastval { get; set; }
private double lasteps { get; set; }
public Epsalg(int nmax, double epss)
{
this.e = new double[nmax];
this.n = 0;
this.ncv = 0;
this.cnvgd = false;
this.eps = epss;
this.lastval = 0.0;
small = float.MinValue * 10.0;
big = double.MaxValue;
}
public double next(double sum)
{
e[n] = sum;
double temp2 = 0.0;
for (int j = n; j > 0; j--)
{
double temp1 = temp2;
temp2 = e[j - 1];
double diff = e[j] - temp2;
if (Math.Abs(diff) <= small)
{
e[j - 1] = big;
}
else
{
e[j - 1] = temp1 + 1.0 / diff;
}
}
n++;
double val = (n & 1) != 0 ? e[0] : e[1];
if (Math.Abs(val) > 0.01 * big)
{
val = lastval;
}
lasteps = Math.Abs(val - lastval);
if (lasteps > eps)
{
ncv = 0;
}
else
{
ncv++;
}
if (ncv >= 3)
{
cnvgd = true;
}
return (lastval = val);
}
}
}