xuhai777 发表于 2018-10-13 21:23:39

分享:N点的多项式拟合曲线,C代码

本帖最后由 xuhai777 于 2018-10-13 21:42 编辑

已知N个样本点,用多项式拟合过这N个点的曲线.
理论的话就不多说了.
n次多项式:Y=ax^n+bx^(n-1)...fx^1+g
已知n次多项式的(n+1)个样本,用消元法求解多项式的系数
思路:
1)多项式按X的幂由低到高排序格式
a+bx+cx^2...+gx^n=Y
2)转换格式:n次则有(n+1)系数,加上Y值,所以列数是(n+2)
a,b,c...g,y
3)把(n+1)个样本组数分别代入,并计算X的幂,书写矩阵格式,行数是(n+1)
4)从左到右顺序设置主系数,开始消元并归1化,直到第n系数先被计算出来
消元:已归1化后的行,异行同列相减,可使主系数为0
归1化:行内全部系数除以主系数
5)把n系数回代入(n-1)行,计算(n-1)系数
再把n和(n-1)系数回代入(n-2)行,计算(n-2)系数
依此法,直到计算出全部系数,系数在末列
限制条件:
样本唯一的x值对应唯一的y值,也就是多项式的曲线不能分叉

例举:已知3点{1,2 ,2,4 ,4,3},求过此3点的多项式曲线
解法:设此曲线的多项式为 a+bx+cx^2=Y
(1)分别代入3点数据,列出矩阵式
1 1 12行1
1 2 44行2
1 4 16 3行3
(2)消元并归1化,计算出n系数
行2=行2-行1 ;行3=行3-行1
   1 1 12行1
=> 0 1 32行2
   0 3 15 1行3
行3归1化
   1 1 1 2    行1
=> 0 1 3 2    行2
   0 1 5 1/3行3
行3=行3-行2
   1 1 1 2   行1
=> 0 1 3 2   行2
   0 0 2 -5/3行3
行3归1化
   1 1 1 2   行1
=> 0 1 3 2   行2
   0 0 1 -5/6行3
(3)回代,直到计算出全部系数
行3代入行2
   1 1 1 2   行1
=> 0 1 0 9/2   行2
   0 0 1 -5/6行3
行3行2代入行1
   1 0 0 -5/3行1
=> 0 1 0 9/2   行2
   0 0 1 -5/6行3
(4)所求多项式
-5/3 +9/2x -5/6x^2 =Y

C语言代码
//float s[]={1,2 ,2,4 ,4,3 ,5,2 ,7,-1 ,7.5,0.5}; //样本:x,y
float s[]={1,2 ,2,4 ,4,3 ,5,2 ,7,-1 ,6,0.5}; //样本:x,y
//float s[]={1,2 ,2,4 ,3,6}; //直线,计算结果中无用系数是0
#define n (sizeof(s)/sizeof(float)/2) //样本组数,行数
#define m (n+1) //矩阵行变量数
//---------------------------
float Pow(float i,int j) //幂函数,x^0=1;x^1=x
{ float k=1;
while(j--) { k*=i; };
return(k);
}
void poly(void)
{ int i,j,k,z,r;
float t,w; //n*(n+1),计算用的矩阵数组,计算结果在末列
if(n>1)
{ z=0; k=0; //初始化矩阵,顺序:x^0,x^1,x^2...y
    for(j=0;j<n;j++)
    { w=s; //X值
      for(i=0;i<n;i++) //第一列总是1,没优化
      { t=Pow(w,i); } //X的幂计算
      t=s; //Y值
    }
    //-----------------------
    for(k=0;k<n;k++) //总元数
    { z=k*m; //初行,参考行
      for(j=k+1;j<n;j++) //行数
      { r=j*m; //始行,消元行
      for(i=k;i<m;i++) //列数
      { t-=t; } //消元
      r++;
      if(t!=1) //行元位置
      { for(i=k+1;i<n;i++) //列数
          { t/=t; } //行归1化
          t=1; //为了好看
      }
      }
    }
    //-----------------------
    for(j=n-1;j>0;j--) //行
    { w=0;
      for(i=j;i<n;i++) //列
      { w+=t*t; }
      t-=w; //计算行Y植
      z=m*(j-1); for(i=j;i<n;i++) { t=0; } //为了好看
    }
}
while(1); //断点
}
//===========================
int main(void)
{ poly();
while(1);
}

xuhai777 发表于 2018-10-13 21:24:49

总结:
1)过有限点的多项式曲线,实际有无数条,因为无穷次多项式可以过有限点.
2)当多项式的项数仅比样本多1时,仅能确定1条曲线.
3)新样本X值在旧样本X范围之外,则新样本Y不可预测;
之内,则新样本Y与原曲线的插值Y偏差较小(相对Ymax~Ymin范围).

xuhai777 发表于 2018-10-13 21:27:55

这个多项式拟合曲线有什么用啊?
只能做插值.不能做预测.
想用它来预测股票走势是不可能的了

xuhai777 发表于 2018-10-13 21:28:37

这个多项式拟合曲线有什么用啊?
只能做插值.不能做预测.
想用它来预测股票走势是不可能的了

xuhai777 发表于 2018-10-13 21:32:45

长宽网络上传不了图片,只有文字版了{:tongue:}

No.5 发表于 2018-10-13 21:34:21

你这自问自答的挺嗨啊。标题注意一下?

xuhai777 发表于 2018-10-13 21:43:14

No.5 发表于 2018-10-13 21:34
你这自问自答的挺嗨啊。标题注意一下?

谢谢提醒

kms2hh 发表于 2018-10-13 21:45:16

好资料,学习了

s1j2h3 发表于 2018-10-13 22:06:02

最小二乘

了无 发表于 2018-10-13 23:17:58

最近刚好需要,收藏一下

chenchaoting 发表于 2018-10-13 23:22:10

感觉用梯度下降之类更简单的,这个最小二乘计算还是比较复杂

atl0402 发表于 2018-10-14 00:29:56

看不懂有啥用,有没有多点校正的例子

eliterxzgxu 发表于 2018-10-14 07:12:50

感谢楼主分享

nanfang2000 发表于 2018-10-14 08:07:00

全是r,j,i,k的代码可读性太差了。。。

shangxf 发表于 2018-10-14 14:25:31

N点的多项式拟合曲线

xuhai777 发表于 2018-10-14 16:20:52

nanfang2000 发表于 2018-10-14 08:07
全是r,j,i,k的代码可读性太差了。。。

我也想知道怎么可以"看一眼就知道整段程序代码是实现什么功能,而且还能看明白每行代码运行的细节"

xuhai777 发表于 2018-10-14 16:25:20

做图验证可以用SketchPad(几何画板),长宽网络上传不了{:tongue:}

locky_z 发表于 2018-10-14 23:05:50

s1j2h3 发表于 2018-10-13 22:06
最小二乘

LZ说的是拟合成一元高次方程,是可以曲线的;而最小二乘法拟合出来的是一元一次线性方程

xingjianpeng 发表于 2018-10-15 08:45:48

其实没有看的很明白。
就是有样本,原来的插值计算没有这样的计算更精确?

zouzhichao 发表于 2018-10-15 08:47:26

locky_z 发表于 2018-10-14 23:05
LZ说的是拟合成一元高次方程,是可以曲线的;而最小二乘法拟合出来的是一元一次线性方程 ...

你确定你的知识没搞错?

s1j2h3 发表于 2018-10-15 09:15:44

locky_z 发表于 2018-10-14 23:05
LZ说的是拟合成一元高次方程,是可以曲线的;而最小二乘法拟合出来的是一元一次线性方程 ...

最小二乘是能处理高次曲线的,我甚至做过椭球拟合
非线性函数最小二乘也是能够处理的

{:smile:}

了无 发表于 2018-10-15 11:35:34

怎么使用呢?有demo吗

zouzhichao 发表于 2018-10-15 12:19:08

s1j2h3 发表于 2018-10-15 09:15
最小二乘是能处理高次曲线的,我甚至做过椭球拟合
非线性函数最小二乘也是能够处理的



是的,多项式的最小二乘法拟合是可以直接计算出参数的,其他函数的最小二乘法拟合通常就需要用到迭代了

s1j2h3 发表于 2018-10-15 12:59:22

zouzhichao 发表于 2018-10-15 12:19
是的,多项式的最小二乘法拟合是可以直接计算出参数的,其他函数的最小二乘法拟合通常就需要用到迭代了 ...

同道中人{:handshake:}

huangqi412 发表于 2018-10-20 18:33:51

楼主还想预测股票
页: [1]
查看完整版本: 分享:N点的多项式拟合曲线,C代码