C#,码海拾贝(06)——连分式(Continued Fraction)曲线插值算法,《C#数值计算算法编程》源代码升级改进版
Posted 深度混淆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#,码海拾贝(06)——连分式(Continued Fraction)曲线插值算法,《C#数值计算算法编程》源代码升级改进版相关的知识,希望对你有一定的参考价值。
一、连分式法
连分式法是一种有理函数逼近法,其基本出发点是:将原型展开成连分式,然后截取前面几个起主要作用的偏系数构成简化模型,连分式法计算简便,拟合精度较高,是一种很有效的传递函数简化法。
Continued Fraction
In mathematics, a continued fraction is an expression obtained through an iterative process of representing a number as the sum of its integer part and the reciprocal of another number, then writing this other number as the sum of its integer part and another reciprocal, and so on. In a finite continued fraction (or terminated continued fraction), the iteration/recursion is terminated after finitely many steps by using an integer in lieu of another continued fraction.
在数学中,连分式是通过迭代过程获得的表达式,将一个数表示为其整数部分和另一个数的倒数的和,然后将该另一个数字写成其整数部分与另一个倒数的和,在有限的连续分数(或终止的连续分数)中,通过使用整数代替另一个连续分数,在有限多个步骤之后终止迭代/递归。
Continued fractions have been studied for over two thousand years, with one of the first recorded studies being that of Euclid around 300 BC (in his book Elements) when he used them to find the greatest common divisor of two integers (using what is known today as the Euclidean algorithm).
Since then, continued fractions have shown up in a variety of other areas, including, but not limited to,
rational approximations for real numbers
solving linear Diophantine equations
solving Pell's equation
approximating PI
连分式已经被研究了两千多年,最早有记录的研究之一是公元前300年左右的欧几里得(在他的《元素》一书中),当时他用它们来寻找两个整数的最大公约数(使用今天所说的欧几里得算法)。
从那时起,连分式已经出现在各种其他领域,包括但不限于,
- 实数的有理逼近
- 求解线性丢番图方程
- 求解佩尔方程
- 近似PI
二、改进代码
using System;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
namespace Zhou.CSharp.Algorithm
/// <summary>
/// 插值计算类Interpolation.cs
/// 作者:周长发
/// 改编:深度混淆
/// https://blog.csdn.net/beijinghorn
/// </summary>
public static partial class Interpolation
/// <summary>
/// 连分式不等距插值
/// </summary>
/// <param name="x">一维数组,长度为n,存放给定的n个结点的值x(i),要求x(0)<x(1)<...<x(n-1)</param>
/// <param name="y">一维数组,长度为n,存放给定的n个结点的函数值y(i),y(i) = f(x(i)), i=0,1,...,n-1</param>
/// <param name="t">存放指定的插值点的x值</param>
/// <returns>指定的查指点t的函数近似值y=f(t)</returns>
public static double Continued_Fraction(double[] x, double[] y, double t)
int n = x.Length;
double z = 0.0;
// 特例处理
if (n < 1)
return (z);
else if (n == 1)
z = y[0];
return (z);
// 连分式插值
int k = 0;
int m = 0;
if (n <= 8)
k = 0;
m = n;
else if (t < x[4])
k = 0;
m = 8;
else if (t > x[n - 5])
k = n - 8;
m = 8;
else
k = 1;
int j = n;
while (j - k != 1)
int i = (k + j) / 2;
if (t < x[i - 1])
j = i;
else
k = i;
k = k - 4;
m = 8;
double[] b = new double[8];
b[0] = y[k];
for (int i = 2; i <= m; i++)
double h = y[i + k - 1];
int w = 0;
int j = 1;
while ((w == 0) && (j <= i - 1))
if (Math.Abs(h - b[j - 1]) < float.Epsilon)
w = 1;
else
h = (x[i + k - 1] - x[j + k - 1]) / (h - b[j - 1]);
j = j + 1;
b[i - 1] = h;
if (w != 0)
b[i - 1] = float.MaxValue;// 1.0e+35;
z = b[m - 1];
for (int i = m - 1; i >= 1; i--)
z = b[i - 1] + (t - x[i + k - 1]) / z;
return (z);
/// <summary>
/// 连分式等距插值
/// (使用非等距插值的方法)
/// </summary>
/// <param name="x0">存放等距n个结点中第一个结点的值</param>
/// <param name="step">等距结点的步长</param>
/// <param name="y">一维数组,长度为n,存放给定的n个结点的函数值y(i),y(i) = f(x(i)), i=0,1,...,n-1</param>
/// <param name="t">存放指定的插值点的x值</param>
/// <returns>指定的查指点t的函数近似值y=f(t)</returns>
public static double Continued_Fraction(double x0, double step, double[] y, double t)
double[] x = new double[y.Length];
for (int i = 0; i < y.Length; i++, x0 += step)
x[i] = x0;
return Continued_Fraction(x, y, t);
#if __OLD__
/// <summary>
/// 连分式等距插值
/// </summary>
/// <param name="x0">存放等距n个结点中第一个结点的值</param>
/// <param name="step">等距结点的步长</param>
/// <param name="y">一维数组,长度为n,存放给定的n个结点的函数值y(i),y(i) = f(x(i)), i=0,1,...,n-1</param>
/// <param name="t">存放指定的插值点的x值</param>
/// <returns>指定的查指点t的函数近似值y=f(t)</returns>
public static double Continued_Fraction(double x0, double step, double[] y, double t)
int n = y.Length;
double z = 0.0;
// 特例处理
if (n < 1)
return (z);
else if (n == 1)
z = y[0];
return (z);
// 连分式插值
int k = 0;
int m = 0;
if (n <= 8)
k = 0;
m = n;
else if (t < (x0 + 4.0 * step))
k = 0;
m = 8;
else if (t > (x0 + (n - 5) * step))
k = n - 8;
m = 8;
else
k = (int)((t - x0) / step) - 3;
m = 8;
double[] b = new double[8];
b[0] = y[k];
for (int i = 2; i <= m; i++)
double hh = y[i + k - 1];
int l = 0;
int j = 1;
while ((l == 0) && (j <= i - 1))
if (Math.Abs(hh - b[j - 1]) + 1.0 == 1.0)
l = 1;
else
double xi = x0 + (i + k - 1) * step;
double xj = x0 + (j + k - 1) * step;
hh = (xi - xj) / (hh - b[j - 1]);
j = j + 1;
b[i - 1] = hh;
if (l != 0)
b[i - 1] = float.MaxValue;// 1.0e+35;
z = b[m - 1];
for (int i = m - 1; i >= 1; i--)
z = b[i - 1] + (t - (x0 + (i + k - 1) * step)) / z;
return (z);
#endif
POWER BY 315SOFT.COM
基于坐标点的计算,从点集计算插值曲线等拓展方法请参阅《拉格朗日插值算法及其拓展》
海边拾贝,第三方网站
第三方网站,不定期更新:
Redis:https://redis.io/documentation
C++ Core Guidelines:http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
以上是关于C#,码海拾贝(06)——连分式(Continued Fraction)曲线插值算法,《C#数值计算算法编程》源代码升级改进版的主要内容,如果未能解决你的问题,请参考以下文章