当我们拥有一组散点图数据时,通常更愿意看到其走势。

对现有数据进行拟合,并输出拟合优度是常用的方法之一。

拟合结果正确性的验证,可以使用excel自带的功能。

下面是c++代码的实现:

  1. #ifndef __Fit_h__
  2. #define __Fit_h__
  3.  
  4. #include <vector>
  5.  
  6. template<size_t Degree>
  7. class CFit
  8. {
  9. public:
  10. CFit(std::vector<double>& xArr,std::vector<double>& yArr):m_xArr(xArr),m_yArr(yArr),m_ssr(0.0),m_sse(0.0),m_rmse(0.0){m_bFitYet = false;}
  11.  
  12. ~CFit(){}
  13. protected:
  14. //- 高斯消除
  15. template<size_t realDegree>
  16. static void GaussianElimination(double (&matrix)[realDegree+1][realDegree+2]
  17. ,double (&coeArr)[realDegree+1])
  18. {
  19. int i,j,k;
  20. for (i = 0; i< realDegree; i++ ) //loop to perform the gauss elimination
  21. {
  22. for (k = i+1; k < (realDegree+1); k++)
  23. {
  24. double t = matrix[k][i]/matrix[i][i];
  25. for (j=0;j<=(realDegree+1);j++)
  26. matrix[k][j] -= t*matrix[i][j]; //make the elements below the pivot elements equal to zero or elimnate the variables
  27. }
  28. }
  29. for (i = realDegree; i >= 0; i--) //back-substitution
  30. { //x is an array whose values correspond to the values of x,y,z..
  31. coeArr[i] = matrix[i][realDegree+1]; //make the variable to be calculated equal to the rhs of the last equation
  32. for (j=0;j<(realDegree+1);j++)
  33. if (j!=i) //then subtract all the lhs values except the coefficient of the variable whose value is being calculated
  34. coeArr[i] -= matrix[i][j]*coeArr[j];
  35. coeArr[i] = coeArr[i]/matrix[i][i]; //now finally divide the rhs by the coefficient of the variable to be calculated
  36. }
  37. }
  38.  
  39. ///
  40. /// \brief 根据x获取拟合方程的y值
  41. /// \return 返回x对应的y值
  42. ///
  43. template<typename T>
  44. double getY(const T x) const
  45. {
  46. double ans(0);
  47. for (size_t i=0;i<(Degree+1);++i)
  48. {
  49. ans += m_coefficientArr[i]*pow((double)x,(int)i);
  50. }
  51. return ans;
  52. }
  53.  
  54. ///
  55. /// \brief 计算均值
  56. /// \return 均值
  57. ///
  58. template <typename T>
  59. static T Mean(const std::vector<T>& v)
  60. {
  61. return Mean(&v[0],v.size());
  62. }
  63. template <typename T>
  64. static T Mean(const T* v,size_t length)
  65. {
  66. T total(0);
  67. for (size_t i=0;i<length;++i)
  68. {
  69. total += v[i];
  70. }
  71. return (total / length);
  72. }
  73.  
  74. template<typename T>
  75. void calcError(const T* x
  76. ,const T* y
  77. ,size_t length
  78. ,double& r_ssr
  79. ,double& r_sse
  80. ,double& r_rmse
  81. )
  82. {
  83. T mean_y = Mean<T>(y,length);
  84. T yi(0);
  85.  
  86. for (size_t i=0; i<length; ++i)
  87. {
  88. yi = getY(x[i]);
  89. r_ssr += ((yi-mean_y)*(yi-mean_y));//计算回归平方和
  90. r_sse += ((yi-y[i])*(yi-y[i]));//残差平方和
  91. }
  92. r_rmse = sqrt(r_sse/(double(length)));
  93. }
  94.  
  95. /**
  96. * @brief 根据两组数据进行一元多项式拟合
  97. * @author
  98. * @param [in] int N,数据个数
  99. [in] const std::vector<double>& xArr,横坐标数据
  100. [in] const std::vector<double>& yArr,纵坐标数据
  101. * @param [out] double (&coefficientArr)[Degree+1],拟合结果.一元多项式系数,从低到高
  102. * @return none
  103. * @note none
  104. */
  105. static void PolynomialFit(int N,const std::vector<double>& xArr,const std::vector<double>& yArr,double (&coefficientArr)[Degree+1])
  106. {
  107. int i = 0,j = 0,k = 0;
  108. //const int realDegree = Degree -1;
  109. double X[2*Degree+1] = {0}; //Array that will store the values of sigma(xi),sigma(xi^2),sigma(xi^3)....sigma(xi^2n)
  110. for (i=0;i<2*Degree+1;i++)
  111. {
  112. for (j=0;j<N;j++)
  113. X[i] += pow(xArr[j],i); //consecutive positions of the array will store N,sigma(xi),sigma(xi^2),sigma(xi^3)....sigma(xi^2n)
  114. }
  115. double Y[Degree+1] = {0}; //Array to store the values of sigma(yi),sigma(xi*yi),sigma(xi^2*yi)...sigma(xi^n*yi)
  116. for (i=0;i<Degree+1;i++)
  117. {
  118. for (j=0;j<N;j++)
  119. Y[i] += pow(xArr[j],i)*yArr[j]; //consecutive positions will store sigma(yi),sigma(xi*yi),sigma(xi^2*yi)...sigma(xi^n*yi)
  120. }
  121.  
  122. double B[Degree+1][Degree+2] = {0}; //B is the Normal matrix(augmented) that will store the equations
  123. for (i=0;i<=Degree;i++)
  124. {
  125. for (j=0;j<=Degree;j++)
  126. {
  127. B[i][j] = X[i+j]; //Build the Normal matrix by storing the corresponding coefficients at the right positions except the last column of the matrix
  128. }
  129. B[i][Degree+1] = Y[i]; //load the values of Y as the last column of B(Normal Matrix but augmented)
  130. }
  131.  
  132. GaussianElimination<Degree>(B,coefficientArr);
  133. }
  134. public:
  135. void PolyFit()
  136. {
  137. if (m_xArr.size() == m_yArr.size())
  138. {
  139. PolynomialFit(static_cast<int>(m_xArr.size()),m_xArr,m_yArr,m_coefficientArr);
  140. m_bFitYet = true;
  141. calcError(&m_xArr[0],&m_yArr[0],static_cast<int>(m_xArr.size()),m_ssr,m_sse,m_rmse);
  142. }
  143. }
  144. //- 一元多项式计算
  145. double UnaryPolynomialCalc(double dX)
  146. {
  147. double dY = 0.0;
  148. for (size_t ulDegree = 0; ulDegree <= Degree; ++ulDegree)
  149. {
  150. dY += pow(dX,(double)ulDegree) * m_coefficientArr[ulDegree];
  151. }
  152. return m_bFitYet ? dY : 0.0;
  153. }
  154.  
  155. ///
  156. /// \brief 剩余平方和
  157. /// \return 剩余平方和
  158. ///
  159. double getSSE(){return m_sse;}
  160. ///
  161. /// \brief 回归平方和
  162. /// \return 回归平方和
  163. ///
  164. double getSSR(){return m_ssr;}
  165. ///
  166. /// \brief 均方根误差
  167. /// \return 均方根误差
  168. ///
  169. double getRMSE(){return m_rmse;}
  170. ///
  171. /// \brief 确定系数,系数是0~1之间的数,是数理上判定拟合优度(goodness-of-fit)的一个量
  172. /// \return 确定系数
  173. ///
  174. double getR_square(){return 1-(m_sse/(m_ssr+m_sse));}
  175.  
  176. ///
  177. /// \brief 根据阶次获取拟合方程的系数,
  178. /// 如getFactor(2),就是获取y=a0+a1*x+a2*x^2+……+apoly_n*x^poly_n中a2的值
  179. /// \return 拟合方程的系数
  180. ///
  181. double getFactor(size_t i)
  182. {
  183. return (i <= Degree) ? m_coefficientArr[i] : 0.0;
  184. }
  185.  
  186. private:
  187. double m_coefficientArr[Degree+1];
  188. const std::vector<double>& m_xArr;
  189. const std::vector<double>& m_yArr;
  190. bool m_bFitYet;//- 一元多项式计算时多项式拟合是否完成 [1/6/2017 wWX210786]
  191.  
  192. double m_ssr; ///<回归平方和
  193. double m_sse; ///<(剩余平方和)
  194. double m_rmse; ///<RMSE均方根误差
  195. };
  196.  
  197. #endif // __Fit_h__

  使用起来也很方便:

  1. double y[] = {7,16,6,18,6,6,10,8};
  2. double x[] = {-109.71,-101.81,-103.83,-99.89,-90,-112.17,-93.5,-96.13};
  3. std::vector<double> xArr(std::begin(x),std::end(x));
  4. std::vector<double> yArr(std::begin(y),std::end(y));
  5. typedef CFit<4> LineFit;
  6. LineFit objPolyfit(xArr,yArr);
  7. objPolyfit.PolyFit();
  8. std::wstring coeArr[] = {L"",L"x",L"x²",L"x\u00b3",L"x "};
  9. CString info(_T("y = "));
  10. for (int i=1;i>=0;i--)
  11. info.AppendFormat(_T("+( %f%s )"),objPolyfit.m_coefficientArr[i],coeArr[i].c_str());
  12.  
  13. std::wcout << info.GetString() << "\n";
  14.  
  15. //std::wcout << "斜率 = " << objPolyfit.getFactor(1) << "\n";
  16. //std::wcout << "截距 = " << objPolyfit.getFactor(0) << "\n";
  17. std::wcout << "goodness-of-fit = "<< objPolyfit.getR_square() << "\n";

  

多项式拟合的cpp实现的更多相关文章

  1. 最小二乘法多项式拟合的Java实现

    背景 由项目中需要根据一些已有数据学习出一个y=ax+b的一元二项式,给定了x,y的一些样本数据,通过梯度下降或最小二乘法做多项式拟合得到a.b,解决该问题时,首先想到的是通过spark mllib去 ...

  2. 数据拟合:多项式拟合polynomial curve fitting

    http://blog.csdn.net/pipisorry/article/details/49804441 常见的曲线拟合方法 1.使偏差绝对值之和最小 2.使偏差绝对值最大的最小       3 ...

  3. matlab练习程序(最小二乘多项式拟合)

    最近在分析一些数据,就是数据拟合的一些事情,用到了matlab的polyfit函数,效果不错. 因此想了解一下这个多项式具体是如何拟合出来的,所以就搜了相关资料. 这个文档介绍的还不错,我估计任何一本 ...

  4. numpy多项式拟合

    关于解决使用numpy.ployfit进行多项式拟合的时候请注意数据类型,解决问题的思路就是统一把数据变成浮点型,就可以了.这是numpy里面的一个bug,非常low希望后面改善. # coding: ...

  5. MATLAB多项式及多项式拟合

    多项式均表示为数组形式,数组元素为多项式降幂系数 1.      polyval函数 求多项式在某一点或某几个点的值. p = [1,1,1];%x^2+x+1 x = [-1,0,1];y = po ...

  6. Matlab多项式拟合測试

    x=0:0.2:4; %生成等差数列 rnd=rand(1,size(x,2))*5; %生成一组随机数 y=x.*x.*x+x.*x+6+rnd; %生成y=x^3+x^2+6函数在垂直方向5个尺度 ...

  7. python多项式拟合:np.polyfit 和 np.polyld

    python数据拟合主要可采用numpy库,库的安装可直接用pip install numpy等. 1. 原始数据:假如要拟合的数据yyy来自sin函数,np.sin import numpy as ...

  8. 利用Python进行多项式拟合

    多项式拟合的简单代码: import matplotlib.pyplot as plt import numpy as np x=[,,,,,,,] y=[,,,,,,,] a=np.polyfit( ...

  9. matlab多项式拟合以及指定函数拟合

    clc;clear all;close all;%% 多项式拟合指令:% X = [1 2 3 4 5 6 7 8 9 ];% Y = [9 7 6 3 -1 2 5 7 20]; % P= poly ...

随机推荐

  1. switch 语句的反汇编浅析

    switch 的简单情景(case 不超过 3 项) 首先,我们分析一下 switch 语句的一种简单情景,我们可以用 C 写出如下如下代码. 编译后用 OllyDBG 载入,它将显示出如下的反汇编代 ...

  2. js:多种方法实现数组去重

    面试的时候数组去重要多种方法实现, 只想到一种判断重复删除的方法,而且还没写对.后来大概看了一下网上的方法. 下午想到一个网上没见过的filter方法,于是整理了一下,基于以前看到的思想,然后用了一些 ...

  3. spi简介(自我理解)

    因为项目中用到spi总线,网上看了下资料,总感觉云山雾罩的,就向身边的同事问了下,他给我解释了下, 我现在把自己理解的写下来 spi一共四条线,一条选择线,一条数据线,2条数据线.spi是一对多设备, ...

  4. 【ACM】nyoj_305_表达式求值_201308081018

    表达式求值时间限制:3000 ms  |  内存限制:65535 KB 难度:3描述 Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近又学会了一些简单的函数求值,比如,它知道函数min(20, ...

  5. spring boot使用外部tomcat部署

    1:pom里面的packaging修改为war(<packaging>war</packaging>) 2:在pom依赖spring-boot-starter-web排除内置的 ...

  6. ios自己定义类(UIView)代码生成简单的UITableViewCell

    因为一个项目中有大量的UITableViewCell须要书写,样式几乎相同都是 文字介绍:显示内容 这种. 自己又懒得写UITableViewCell类嫌不是必需:在方法tableView:cellF ...

  7. chcp - 设置或者显示活动代码页编号

    chcp - 设置或者显示活动代码页编号 学习了:https://baike.baidu.com/item/CHCP/9061635?fr=aladdin

  8. android发送get请求时报错

    异常信息: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.synology.synologycloud/ ...

  9. C++设计模式之状态模式(二)

    2.智能空调的设计与实现 某软件公司将开发一套智能空调系统: 系统检測到温度处于20---30度之间,则切换到常温状态:温度处于30---45度,则切换到制冷状态: 温度小于20度,则切换到制热状态. ...

  10. 【cl】控制台执行Java程序

    1.设置CLASSPATH环境变量,指向package所在的目录,一般是项目文件夹的bin目录 2.执行 java  package.ClassName linux: 方法一: 步骤1:export ...