NLequation.cpp
上传用户:weigute
上传日期:2007-03-02
资源大小:1287k
文件大小:31k
源码类别:

数学计算

开发平台:

Visual C++

  1. //////////////////////////////////////////////////////////////////////
  2. // NLequation.cpp
  3. //
  4. // 求解线性方程组的类 CNLequation 的实现代码
  5. //
  6. // 周长发编制, 2002/8
  7. //////////////////////////////////////////////////////////////////////
  8. #include "stdafx.h"
  9. #include "NLequation.h"
  10. #include "LEquations.h"
  11. #ifdef _DEBUG
  12. #undef THIS_FILE
  13. static char THIS_FILE[]=__FILE__;
  14. #define new DEBUG_NEW
  15. #endif
  16. //////////////////////////////////////////////////////////////////////
  17. // Construction/Destruction
  18. //////////////////////////////////////////////////////////////////////
  19. //////////////////////////////////////////////////////////////////////
  20. // 基本构造函数
  21. //////////////////////////////////////////////////////////////////////
  22. CNLequation::CNLequation()
  23. {
  24. }
  25. //////////////////////////////////////////////////////////////////////
  26. // 析构函数
  27. //////////////////////////////////////////////////////////////////////
  28. CNLequation::~CNLequation()
  29. {
  30. }
  31. //////////////////////////////////////////////////////////////////////
  32. // 求非线性方程实根的对分法
  33. //
  34. // 调用时,须覆盖计算方程左端函数f(x)值的虚函数double Func(double x)
  35. //
  36. // 参数:
  37. // 1. int nNumRoots - 在[xStart, xEnd]内实根个数的预估值
  38. // 2. double x[] - 一维数组,长度为m。返回在区间[xStart, xEnd]内搜索到
  39. //                 的实根,实根个数由函数值返回
  40. // 3. double xStart - 求根区间的左端点
  41. // 4. double xEnd - 求根区间的右端点
  42. // 5. double dblStep - 搜索求根时采用的步长
  43. // 6. double eps - 精度控制参数,默认值为0.000001
  44. //
  45. // 返回值:int 型,求得的实根的数目
  46. //////////////////////////////////////////////////////////////////////
  47. int CNLequation::GetRootBisect(int nNumRoots, double x[], double xStart, double xEnd, double dblStep, double eps /*= 0.000001*/)
  48. {
  49. int n,js;
  50.     double z,y,z1,y1,z0,y0;
  51. // 根的个数清0
  52.     n = 0; 
  53. // 从左端点开始搜索
  54. z = xStart; 
  55. y = Func(z);
  56. // 循环求解
  57.     while ((z<=xEnd+dblStep/2.0)&&(n!=nNumRoots))
  58.     { 
  59. if (fabs(y)<eps)
  60.         { 
  61. n=n+1; 
  62. x[n-1]=z;
  63.             z=z+dblStep/2.0; 
  64. y=Func(z);
  65.         }
  66.         else
  67.         { 
  68. z1=z+dblStep; 
  69. y1=Func(z1);
  70.             
  71. if (fabs(y1)<eps)
  72.             { 
  73. n=n+1; 
  74. x[n-1]=z1;
  75.                 z=z1+dblStep/2.0; 
  76. y=Func(z);
  77.             }
  78.             else if (y*y1>0.0)
  79.             { 
  80. y=y1; 
  81. z=z1;
  82. }
  83.             else
  84.             { 
  85. js=0;
  86.                 while (js==0)
  87.                 { 
  88. if (fabs(z1-z)<eps)
  89.                     { 
  90. n=n+1; 
  91. x[n-1]=(z1+z)/2.0;
  92.                         z=z1+dblStep/2.0; y=Func(z);
  93.                         js=1;
  94.                     }
  95.                     else
  96.                     { 
  97. z0=(z1+z)/2.0; 
  98. y0=Func(z0);
  99.                         if (fabs(y0)<eps)
  100.                         { 
  101. x[n]=z0; 
  102. n=n+1; 
  103. js=1;
  104.                             z=z0+dblStep/2.0; 
  105. y=Func(z);
  106.                         }
  107.                         else if ((y*y0)<0.0)
  108.                         { 
  109. z1=z0; 
  110. y1=y0;
  111. }
  112.                         else 
  113. z=z0; 
  114. y=y0;
  115. }
  116.                     }
  117.                 }
  118.             }
  119.         }
  120.     }
  121.     
  122. // 返回实根的数目
  123. return(n);
  124. }
  125. //////////////////////////////////////////////////////////////////////
  126. // 求非线性方程一个实根的牛顿法
  127. //
  128. // 调用时,须覆盖计算方程左端函数f(x)及其一阶导数f'(x)值的虚函数
  129. //                  void Func(double x, double y[])
  130. //         y(0) 返回f(x)的值
  131. //         y(1) 返回f'(x)的值
  132. //
  133. // 参数:
  134. // 1. double *x - 传入迭代初值(猜测解),返回在区间求得的一个实根
  135. // 2. int nMaxIt - 递归次数,默认值为60
  136. // 3. double eps - 精度控制参数,默认值为0.000001
  137. //
  138. // 返回值:BOOL 型,求解是否成功
  139. //////////////////////////////////////////////////////////////////////
  140. BOOL CNLequation::GetRootNewton(double* x, int nMaxIt /*= 60*/, double eps /*= 0.000001*/)
  141.     int l;
  142.     double y[2],d,p,x0,x1;
  143. // 条件值
  144.     l=nMaxIt; 
  145. x0=*x;
  146.     Func(x0,y);
  147.     
  148. // 求解,控制精度
  149. d=eps+1.0;
  150.     while ((d>=eps)&&(l!=0))
  151.     { 
  152. if (y[1] == 0.0)
  153. return FALSE;
  154.         x1=x0-y[0]/y[1];
  155.         Func(x1,y);
  156.         
  157. d=fabs(x1-x0); 
  158. p=fabs(y[0]);
  159.         if (p>d) 
  160. d=p;
  161.         x0=x1; 
  162. l=l-1;
  163.     }
  164.     
  165. *x=x1;
  166. return TRUE;
  167. }
  168. //////////////////////////////////////////////////////////////////////
  169. // 求非线性方程一个实根的埃特金迭代法
  170. //
  171. // 调用时,须覆盖计算方程左端函数f(x)值的虚函数double Func(double x)
  172. //
  173. // 参数:
  174. // 1. double *x - 传入迭代初值(猜测解),返回在区间求得的一个实根
  175. // 2. int nMaxIt - 递归次数,默认值为60
  176. // 3. double eps - 精度控制参数,默认值为0.000001
  177. //
  178. // 返回值:BOOL 型,求解是否成功
  179. //////////////////////////////////////////////////////////////////////
  180. BOOL CNLequation::GetRootAitken(double* x, int nMaxIt /*= 60*/, double eps /*= 0.000001*/)
  181. int flag,l;
  182.     double u,v,x0;
  183. // 求解条件
  184.     l=0; 
  185. x0=*x; 
  186. flag=0;
  187. // 迭代求解
  188.     while ((flag==0)&&(l!=nMaxIt))
  189.     { 
  190. l=l+1; 
  191.         u=Func(x0); 
  192. v=Func(u);
  193.         if (fabs(u-v)<eps) 
  194. x0=v; 
  195. flag=1; 
  196. }
  197.         else 
  198. x0=v-(v-u)*(v-u)/(v-2.0*u+x0);
  199.     }
  200.     
  201. *x=x0; 
  202.     
  203. // 是否在指定的迭代次数内达到求解精度
  204. return (nMaxIt > l);
  205. }
  206. //////////////////////////////////////////////////////////////////////
  207. // 求非线性方程一个实根的连分式解法
  208. //
  209. // 调用时,须覆盖计算方程左端函数f(x)值的虚函数double Func(double x)
  210. //
  211. // 参数:
  212. // 1. double *x - 传入迭代初值(猜测解),返回在区间求得的一个实根
  213. // 2. double eps - 精度控制参数,默认值为0.000001
  214. //
  215. // 返回值:BOOL 型,求解是否成功
  216. //////////////////////////////////////////////////////////////////////
  217. BOOL CNLequation::GetRootPq(double* x, double eps /*= 0.000001*/)
  218.     int i,j,m,it,l;
  219.     double a[10],y[10],z,h,x0,q;
  220. // 求解条件
  221.     l=10; 
  222. q=1.0e+35; 
  223. x0=*x; 
  224. h=0.0;
  225.     
  226. // 连分式求解
  227. while (l!=0)
  228.     { 
  229. l=l-1; 
  230. j=0; 
  231. it=l;
  232.         while (j<=7)
  233.         { 
  234. if (j<=2) 
  235. z=x0+0.1*j;
  236.             else 
  237. z=h;
  238. y[j]=Func(z);
  239.             h=z;
  240.             if (j==0) 
  241. a[0]=z;
  242.             else
  243.             { 
  244. m=0; 
  245. i=0;
  246.                 while ((m==0)&&(i<=j-1))
  247.                 { 
  248. if (fabs(h-a[i])+1.0==1.0) 
  249. m=1;
  250.                     else 
  251. h=(y[j]-y[i])/(h-a[i]);
  252.                      
  253. i=i+1;
  254.                 }
  255.                 a[j]=h;
  256.                 if (m!=0) 
  257. a[j]=q;
  258.                 h=0.0;
  259.                 for (i=j-1; i>=0; i--)
  260.                 { 
  261. if (fabs(a[i+1]+h)+1.0==1.0) 
  262. h=q;
  263.                     else 
  264. h=-y[i]/(a[i+1]+h);
  265.                 }
  266.                  
  267. h=h+a[0];
  268.             }
  269.              
  270. if (fabs(y[j])>=eps) 
  271. j=j+1;
  272.             else 
  273. j=10; 
  274. l=0;
  275. }
  276. }
  277.         
  278. x0=h;
  279. }
  280.     *x=h;
  281.     
  282. // 是否在10阶连分式内求的实根?
  283. return (10>it);
  284. }
  285. //////////////////////////////////////////////////////////////////////
  286. // 求实系数代数方程全部根的QR方法
  287. //
  288. // 参数:
  289. // 1. int n - 多项式方程的次数
  290. // 2. double dblCoef[] - 一维数组,长度为n+1,按降幂次序依次存放n次多项式方程的n+1个系数
  291. // 3. double xr[] - 一维数组,长度为n,返回n个根的实部
  292. // 4. double xi[] - 一维数组,长度为n,返回n个根的虚部
  293. // 5. int nMaxIt - 迭代次数,默认值为 60
  294. // 6. double eps - 精度控制参数,默认值为 0.000001
  295. //
  296. // 返回值:BOOL 型,求解是否成功
  297. //////////////////////////////////////////////////////////////////////
  298. BOOL CNLequation::GetRootQr(int n, double dblCoef[], double xr[], double xi[], int nMaxIt /*= 60*/, double eps /*= 0.000001*/)
  299. // 初始化矩阵
  300. CMatrix mtxQ;
  301. mtxQ.Init(n, n);
  302.     double *q = mtxQ.GetData();
  303. // 构造赫申伯格矩阵
  304.     for (int j=0; j<=n-1; j++)
  305. q[j]=-dblCoef[n-j-1]/dblCoef[n];
  306.     for (j=n; j<=n*n-1; j++)
  307. q[j]=0.0;
  308.     for (int i=0; i<=n-2; i++)
  309. q[(i+1)*n+i]=1.0;
  310. // 求赫申伯格矩阵的特征值和特征向量,即为方程的解
  311.     if (mtxQ.HBergEigenv(xr, xi, nMaxIt, eps))
  312. return TRUE;
  313. return FALSE;
  314. }
  315. //////////////////////////////////////////////////////////////////////
  316. // 求实系数代数方程全部根的牛顿下山法
  317. //
  318. // 参数:
  319. // 1. int n - 多项式方程的次数
  320. // 2. double dblCoef[] - 一维数组,长度为n+1,按降幂次序依次存放n次多项式方程的n+1个系数
  321. // 3. double xr[] - 一维数组,长度为n,返回n个根的实部
  322. // 4. double xi[] - 一维数组,长度为n,返回n个根的虚部
  323. //
  324. // 返回值:BOOL 型,求解是否成功
  325. //////////////////////////////////////////////////////////////////////
  326. BOOL CNLequation::GetRootNewtonDownHill(int n, double dblCoef[], double xr[], double xi[])
  327. int m,i,jt,k,is,it;
  328.     double t,x,y,x1,y1,dx,dy,p,q,w,dd,dc,c;
  329.     double g,u,v,pq,g1,u1,v1;
  330.     
  331. // 初始判断
  332.     m=n;
  333.     while ((m>0)&&(fabs(dblCoef[m])+1.0==1.0)) 
  334. m=m-1;
  335. // 求解失败
  336.     if (m<=0)
  337. return FALSE;
  338.     for (i=0; i<=m; i++)
  339. dblCoef[i]=dblCoef[i]/dblCoef[m];
  340.     
  341. for (i=0; i<=m/2; i++)
  342.     { 
  343. w=dblCoef[i]; 
  344. dblCoef[i]=dblCoef[m-i]; 
  345. dblCoef[m-i]=w;
  346. }
  347.     
  348. // 迭代求解
  349. k=m; 
  350. is=0; 
  351. w=1.0;
  352.     jt=1;
  353.     while (jt==1)
  354.     { 
  355. pq=fabs(dblCoef[k]);
  356. while (pq<1.0e-12)
  357.         { 
  358. xr[k-1]=0.0; 
  359. xi[k-1]=0.0; 
  360. k=k-1;
  361.             if (k==1)
  362.             { 
  363. xr[0]=-dblCoef[1]*w/dblCoef[0]; 
  364. xi[0]=0.0;
  365.                 
  366. return TRUE;
  367.             }
  368.             
  369. pq=fabs(dblCoef[k]);
  370.         }
  371. q=log(pq); 
  372. q=q/(1.0*k); 
  373. q=exp(q);
  374.         p=q; 
  375. w=w*p;
  376.         for (i=1; i<=k; i++)
  377.         { 
  378. dblCoef[i]=dblCoef[i]/q; 
  379. q=q*p;
  380. }
  381.         
  382. x=0.0001; 
  383. x1=x; 
  384. y=0.2; 
  385. y1=y; 
  386. dx=1.0;
  387.         g=1.0e+37; 
  388. l40:
  389.         u=dblCoef[0]; v=0.0;
  390.         for (i=1; i<=k; i++)
  391.         { 
  392. p=u*x1; 
  393. q=v*y1;
  394.             pq=(u+v)*(x1+y1);
  395.             u=p-q+dblCoef[i]; 
  396. v=pq-p-q;
  397.         }
  398.         
  399. g1=u*u+v*v;
  400.         if (g1>=g)
  401.         { 
  402. if (is!=0)
  403.             { 
  404. it=1;
  405.                 g65(&x,&y,&x1,&y1,&dx,&dy,&dd,&dc,&c,&k,&is,&it);
  406.                 if (it==0) 
  407. goto l40;
  408.             }
  409.             else
  410.             { 
  411. g60(&t,&x,&y,&x1,&y1,&dx,&dy,&p,&q,&k,&it);
  412.                 if (t>=1.0e-03) 
  413. goto l40;
  414.                 
  415. if (g>1.0e-18)
  416.                 { 
  417. it=0;
  418.                     g65(&x,&y,&x1,&y1,&dx,&dy,&dd,&dc,&c,&k,&is,&it);
  419.                     if (it==0) 
  420. goto l40;
  421.                 }
  422.             }
  423.             
  424. g90(xr,xi,dblCoef,&x,&y,&p,&q,&w,&k);
  425.         }
  426.         else
  427.         { 
  428. g=g1; 
  429. x=x1; 
  430. y=y1; 
  431. is=0;
  432.             if (g<=1.0e-22)
  433. g90(xr,xi,dblCoef,&x,&y,&p,&q,&w,&k);
  434.             else
  435.             { 
  436. u1=k*dblCoef[0]; 
  437. v1=0.0;
  438.                 for (i=2; i<=k; i++)
  439.                 { 
  440. p=u1*x; 
  441. q=v1*y; 
  442. pq=(u1+v1)*(x+y);
  443.                     u1=p-q+(k-i+1)*dblCoef[i-1];
  444.                     v1=pq-p-q;
  445.                 }
  446.                 
  447. p=u1*u1+v1*v1;
  448.                 if (p<=1.0e-20)
  449.                 { 
  450. it=0;
  451.                     g65(&x,&y,&x1,&y1,&dx,&dy,&dd,&dc,&c,&k,&is,&it);
  452.                     if (it==0) 
  453. goto l40;
  454.                     g90(xr,xi,dblCoef,&x,&y,&p,&q,&w,&k);
  455.                 }
  456.                 else
  457.                 { 
  458. dx=(u*u1+v*v1)/p;
  459.                     dy=(u1*v-v1*u)/p;
  460.                     t=1.0+4.0/k;
  461.                     g60(&t,&x,&y,&x1,&y1,&dx,&dy,&p,&q,&k,&it);
  462.                     if (t>=1.0e-03) 
  463. goto l40;
  464.                     if (g>1.0e-18)
  465.                     { 
  466. it=0;
  467.                         g65(&x,&y,&x1,&y1,&dx,&dy,&dd,&dc,&c,&k,&is,&it);
  468.                         if (it==0) 
  469. goto l40;
  470.                     }
  471.                     
  472. g90(xr,xi,dblCoef,&x,&y,&p,&q,&w,&k);
  473.                 }
  474.             }
  475.         }
  476.         
  477. if (k==1) 
  478. jt=0;
  479.         else 
  480. jt=1;
  481.     }
  482.     
  483. return TRUE;
  484. }
  485. //////////////////////////////////////////////////////////////////////
  486. // 内部函数
  487. //////////////////////////////////////////////////////////////////////
  488. void CNLequation::g60(double* t,double* x,double* y,double* x1,double* y1,double* dx,double* dy,double* p,double* q,int* k,int* it)
  489. *it=1;
  490.     while (*it==1)
  491.     { 
  492. *t=*t/1.67; 
  493. *it=0;
  494.         *x1=*x-(*t)*(*dx);
  495.         *y1=*y-(*t)*(*dy);
  496.         if (*k>=50)
  497. *p=sqrt((*x1)*(*x1)+(*y1)*(*y1));
  498.             *q=exp(85.0/(*k));
  499.             if (*p>=*q) 
  500. *it=1;
  501.         }
  502.     }
  503. }
  504. //////////////////////////////////////////////////////////////////////
  505. // 内部函数
  506. //////////////////////////////////////////////////////////////////////
  507. void CNLequation::g90(double xr[],double xi[],double dblCoef[],double* x,double* y,double* p,double* q,double* w,int* k)
  508. int i;
  509.     
  510. if (fabs(*y)<=1.0e-06)
  511.     { 
  512. *p=-(*x); 
  513. *y=0.0; 
  514. *q=0.0;
  515. }
  516.     else
  517.     { 
  518. *p=-2.0*(*x); 
  519. *q=(*x)*(*x)+(*y)*(*y);
  520.         xr[*k-1]=(*x)*(*w);
  521.         xi[*k-1]=-(*y)*(*w);
  522.         *k=*k-1;
  523.     }
  524.     
  525. for (i=1; i<=*k; i++)
  526.     { 
  527. dblCoef[i]=dblCoef[i]-dblCoef[i-1]*(*p);
  528.         dblCoef[i+1]=dblCoef[i+1]-dblCoef[i-1]*(*q);
  529.     }
  530.     
  531. xr[*k-1]=(*x)*(*w); 
  532. xi[*k-1]=(*y)*(*w);
  533.     *k=*k-1;
  534.     if (*k==1)
  535.     { 
  536. xr[0]=-dblCoef[1]*(*w)/dblCoef[0]; 
  537. xi[0]=0.0;
  538. }
  539. }
  540. //////////////////////////////////////////////////////////////////////
  541. // 内部函数
  542. //////////////////////////////////////////////////////////////////////
  543. void CNLequation::g65(double* x,double* y,double* x1,double* y1,double* dx,double* dy,double* dd,double* dc,double* c,int* k,int* is,int* it)
  544. if (*it==0)
  545.     { 
  546. *is=1;
  547.         *dd=sqrt((*dx)*(*dx)+(*dy)*(*dy));
  548.         if (*dd>1.0) 
  549. *dd=1.0;
  550.         *dc=6.28/(4.5*(*k)); 
  551. *c=0.0;
  552.     }
  553.     
  554. while(TRUE)
  555.     { 
  556. *c=*c+(*dc);
  557.         *dx=(*dd)*cos(*c); 
  558. *dy=(*dd)*sin(*c);
  559.         *x1=*x+*dx; 
  560. *y1=*y+*dy;
  561.         if (*c<=6.29)
  562.         { 
  563. *it=0; 
  564. return;
  565. }
  566.         
  567. *dd=*dd/1.67;
  568.         if (*dd<=1.0e-07)
  569.         { 
  570. *it=1; 
  571. return;
  572. }
  573.         
  574. *c=0.0;
  575.     }
  576. }
  577. //////////////////////////////////////////////////////////////////////
  578. // 求复系数代数方程全部根的牛顿下山法
  579. //
  580. // 参数:
  581. // 1. int n - 多项式方程的次数
  582. // 2. double ar[] - 一维数组,长度为n+1,按降幂次序依次存放n次多项式方程的n+1个系数的实部
  583. // 3. double ai[] - 一维数组,长度为n+1,按降幂次序依次存放n次多项式方程的n+1个系数的虚部
  584. // 4. double xr[] - 一维数组,长度为n,返回n个根的实部
  585. // 5. double xi[] - 一维数组,长度为n,返回n个根的虚部
  586. //
  587. // 返回值:BOOL 型,求解是否成功
  588. //////////////////////////////////////////////////////////////////////
  589. BOOL CNLequation::GetRootNewtonDownHill(int n, double ar[], double ai[], double xr[], double xi[])
  590. int m,i,jt,k,is,it;
  591.     double t,x,y,x1,y1,dx,dy,p,q,w,dd,dc,c;
  592.     double g,u,v,pq,g1,u1,v1;
  593. // 初始判断
  594.     m=n;
  595.     p=sqrt(ar[m]*ar[m]+ai[m]*ai[m]);
  596.     while ((m>0)&&(p+1.0==1.0))
  597.     {  
  598. m=m-1;
  599.         p=sqrt(ar[m]*ar[m]+ai[m]*ai[m]);
  600.     }
  601.     
  602. // 求解失败
  603. if (m<=0)
  604. return FALSE;
  605.     for (i=0; i<=m; i++)
  606.     { 
  607. ar[i]=ar[i]/p; 
  608. ai[i]=ai[i]/p;
  609. }
  610.     
  611. for (i=0; i<=m/2; i++)
  612.     { 
  613. w=ar[i]; 
  614. ar[i]=ar[m-i]; 
  615. ar[m-i]=w;
  616.         w=ai[i]; 
  617. ai[i]=ai[m-i]; 
  618. ai[m-i]=w;
  619.     }
  620.     
  621. // 迭代求解
  622. k=m; 
  623. is=0; 
  624. w=1.0;
  625.     jt=1;
  626.     while (jt==1)
  627.     { 
  628. pq=sqrt(ar[k]*ar[k]+ai[k]*ai[k]);
  629. while (pq<1.0e-12)
  630.         { 
  631. xr[k-1]=0.0; 
  632. xi[k-1]=0.0; 
  633. k=k-1;
  634.             if (k==1)
  635.             { 
  636. p=ar[0]*ar[0]+ai[0]*ai[0];
  637.                 xr[0]=-w*(ar[0]*ar[1]+ai[0]*ai[1])/p;
  638.                 xi[0]=w*(ar[1]*ai[0]-ar[0]*ai[1])/p;
  639.                 
  640. return TRUE;
  641.             }
  642.             
  643. pq=sqrt(ar[k]*ar[k]+ai[k]*ai[k]);
  644.         }
  645. q=log(pq); 
  646. q=q/(1.0*k); 
  647. q=exp(q);
  648.         p=q; 
  649. w=w*p;
  650.         for (i=1; i<=k; i++)
  651.         { 
  652. ar[i]=ar[i]/q; 
  653. ai[i]=ai[i]/q; 
  654. q=q*p;
  655. }
  656.         
  657. x=0.0001; 
  658. x1=x; 
  659. y=0.2; 
  660. y1=y; 
  661. dx=1.0;
  662.         g=1.0e+37; 
  663. l40:
  664.         u=ar[0]; 
  665. v=ai[0];
  666.         for (i=1; i<=k; i++)
  667.         { 
  668. p=u*x1; 
  669. q=v*y1;
  670.             pq=(u+v)*(x1+y1);
  671.             u=p-q+ar[i]; 
  672. v=pq-p-q+ai[i];
  673.         }
  674.         
  675. g1=u*u+v*v;
  676.         if (g1>=g)
  677.         { 
  678. if (is!=0)
  679.             { 
  680. it=1;
  681.                 g65c(&x,&y,&x1,&y1,&dx,&dy,&dd,&dc,&c,&k,&is,&it);
  682.                 if (it==0) 
  683. goto l40;
  684.             }
  685.             else
  686.             { 
  687. g60c(&t,&x,&y,&x1,&y1,&dx,&dy,&p,&q,&k,&it);
  688.                 if (t>=1.0e-03) 
  689. goto l40;
  690.                 
  691. if (g>1.0e-18)
  692.                 { 
  693. it=0;
  694.                     g65c(&x,&y,&x1,&y1,&dx,&dy,&dd,&dc,&c,&k,&is,&it);
  695.                     if (it==0) 
  696. goto l40;
  697.                 }
  698.             }
  699.             
  700. g90c(xr,xi,ar,ai,&x,&y,&p,&w,&k);
  701.         }
  702.         else
  703.         { 
  704. g=g1; 
  705. x=x1; 
  706. y=y1; 
  707. is=0;
  708.             if (g<=1.0e-22)
  709. g90c(xr,xi,ar,ai,&x,&y,&p,&w,&k);
  710.             else
  711.             { 
  712. u1=k*ar[0]; 
  713. v1=ai[0];
  714.                 for (i=2; i<=k; i++)
  715.                 { 
  716. p=u1*x; 
  717. q=v1*y; 
  718. pq=(u1+v1)*(x+y);
  719.                     u1=p-q+(k-i+1)*ar[i-1];
  720.                     v1=pq-p-q+(k-i+1)*ai[i-1];
  721.                 }
  722.                 
  723. p=u1*u1+v1*v1;
  724.                 if (p<=1.0e-20)
  725.                 { 
  726. it=0;
  727.                     g65c(&x,&y,&x1,&y1,&dx,&dy,&dd,&dc,&c,&k,&is,&it);
  728.                     if (it==0) 
  729. goto l40;
  730.                     
  731. g90c(xr,xi,ar,ai,&x,&y,&p,&w,&k);
  732.                 }
  733.                 else
  734.                 { 
  735. dx=(u*u1+v*v1)/p;
  736.                     dy=(u1*v-v1*u)/p;
  737.                     t=1.0+4.0/k;
  738.                     g60c(&t,&x,&y,&x1,&y1,&dx,&dy,&p,&q,&k,&it);
  739.                     if (t>=1.0e-03) 
  740. goto l40;
  741.                     
  742. if (g>1.0e-18)
  743.                     { 
  744. it=0;
  745.                         g65c(&x,&y,&x1,&y1,&dx,&dy,&dd,&dc,&c,&k,&is,&it);
  746.                         if (it==0) 
  747. goto l40;
  748.                     }
  749.                     
  750. g90c(xr,xi,ar,ai,&x,&y,&p,&w,&k);
  751.                 }
  752.             }
  753.         }
  754.         
  755. if (k==1) 
  756. jt=0;
  757.         else 
  758. jt=1;
  759.     }
  760.     
  761. return TRUE;
  762. }
  763. //////////////////////////////////////////////////////////////////////
  764. // 内部函数
  765. //////////////////////////////////////////////////////////////////////
  766. void CNLequation::g60c(double* t,double* x,double* y,double* x1,double* y1,double* dx,double* dy,double* p,double* q,int* k,int* it)
  767. *it=1;
  768.     while (*it==1)
  769.     { 
  770. *t=*t/1.67; 
  771. *it=0;
  772.         *x1=*x-*t*(*dx);
  773.         *y1=*y-*t*(*dy);
  774.         if (*k>=30)
  775. *p=sqrt(*x1*(*x1)+*y1*(*y1));
  776.             *q=exp(75.0/(*k));
  777.             if (*p>=*q) 
  778. *it=1;
  779.         }
  780.     }
  781. }
  782. //////////////////////////////////////////////////////////////////////
  783. // 内部函数
  784. //////////////////////////////////////////////////////////////////////
  785. void CNLequation::g90c(double xr[],double xi[],double ar[],double ai[],double* x,double* y,double* p,double* w,int* k)
  786. int i;
  787.     for (i=1; i<=*k; i++)
  788.     { 
  789. ar[i]=ar[i]+ar[i-1]*(*x)-ai[i-1]*(*y);
  790.         ai[i]=ai[i]+ar[i-1]*(*y)+ai[i-1]*(*x);
  791.     }
  792.     
  793. xr[*k-1]=*x*(*w); 
  794. xi[*k-1]=*y*(*w);
  795.     *k=*k-1;
  796.     if (*k==1)
  797.     { 
  798. *p=ar[0]*ar[0]+ai[0]*ai[0];
  799.         xr[0]=-*w*(ar[0]*ar[1]+ai[0]*ai[1])/(*p);
  800.         xi[0]=*w*(ar[1]*ai[0]-ar[0]*ai[1])/(*p);
  801.     }
  802. }
  803. //////////////////////////////////////////////////////////////////////
  804. // 内部函数
  805. //////////////////////////////////////////////////////////////////////
  806. void CNLequation::g65c(double* x,double* y,double* x1,double* y1,double* dx,double* dy,double* dd,double* dc,double* c,int* k,int* is,int* it)
  807. if (*it==0)
  808.     { 
  809. *is=1;
  810.         *dd=sqrt(*dx*(*dx)+*dy*(*dy));
  811.         if (*dd>1.0) 
  812. *dd=1.0;
  813.         *dc=6.28/(4.5*(*k)); 
  814. *c=0.0;
  815.     }
  816.     
  817. while(TRUE)
  818.     { 
  819. *c=*c+*dc;
  820.         *dx=*dd*cos(*c); 
  821. *dy=*dd*sin(*c);
  822.         *x1=*x+*dx; 
  823. *y1=*y+*dy;
  824.         if (*c<=6.29)
  825.         { 
  826. *it=0; 
  827. return;
  828. }
  829.         
  830. *dd=*dd/1.67;
  831.         if (*dd<=1.0e-07)
  832.         { 
  833. *it=1; 
  834. return;
  835. }
  836.         
  837. *c=0.0;
  838.     }
  839. }
  840. //////////////////////////////////////////////////////////////////////
  841. // 求非线性方程一个实根的蒙特卡洛法
  842. //
  843. // 调用时,须覆盖计算方程左端函数f(x)值的虚函数double Func(double x)
  844. //
  845. // 参数:
  846. // 1. double* x - 传入初值(猜测解),返回求得的实根
  847. // 2. double xStart - 均匀分布的端点初值
  848. // 3. int nControlB - 控制参数
  849. // 4. double eps - 控制精度,默认值为0.000001
  850. //
  851. // 返回值:无
  852. //////////////////////////////////////////////////////////////////////
  853. void CNLequation::GetRootMonteCarlo(double* x, double xStart, int nControlB, double eps /*= 0.000001*/)
  854. int k;
  855.     double xx,a,y,x1,y1,r;
  856.     
  857. // 求解条件
  858. a = xStart; 
  859. k = 1; 
  860. r = 1.0;
  861. // 初值
  862. xx = *x; 
  863. y = Func(xx);
  864. // 精度控制求解
  865.     while (a>=eps)
  866.     { 
  867. x1=rnd(&r);
  868. x1=-a+2.0*a*x1;
  869.         x1=xx+x1; 
  870. y1=Func(x1);
  871.         
  872. k=k+1;
  873.         if (fabs(y1)>=fabs(y))
  874.         { 
  875. if (k>nControlB) 
  876. k=1; 
  877. a=a/2.0; 
  878. }
  879. }
  880.         else
  881.         { 
  882. k=1; 
  883. xx=x1; 
  884. y=y1;
  885.             if (fabs(y)<eps)
  886.             { 
  887. *x=xx; 
  888. return; 
  889. }
  890.         }
  891.     }
  892.     
  893. *x=xx;
  894. }
  895. //////////////////////////////////////////////////////////////////////
  896. // 内部函数
  897. //////////////////////////////////////////////////////////////////////
  898. double CNLequation::rnd(double* r)
  899. {
  900. int m;
  901.     double s,u,v,p;
  902.     
  903. s=65536.0; 
  904. u=2053.0; 
  905. v=13849.0;
  906.     m=(int)(*r/s); 
  907. *r=*r-m*s;
  908.     *r=u*(*r)+v; 
  909. m=(int)(*r/s);
  910.     *r=*r-m*s; p=*r/s;
  911.     
  912. return(p);
  913. }
  914. //////////////////////////////////////////////////////////////////////
  915. // 求实函数或复函数方程一个复根的蒙特卡洛法
  916. //
  917. // 调用时,须覆盖计算方程左端函数的模值||f(x, y)||的虚函数
  918. //           double Func(double x, double y)
  919. //
  920. // 参数:
  921. // 1. double* x - 传入初值(猜测解)的实部,返回求得的根的实部
  922. // 2. double* y - 传入初值(猜测解)的虚部,返回求得的根的虚部
  923. // 3. double xStart - 均匀分布的端点初值
  924. // 4. int nControlB - 控制参数
  925. // 5. double eps - 控制精度,默认值为0.000001
  926. // 6. double xi[] - 一维数组,长度为n,返回n个根的虚部
  927. //
  928. // 返回值:无
  929. //////////////////////////////////////////////////////////////////////
  930. void CNLequation::GetRootMonteCarlo(double* x, double* y, double xStart, int nControlB, double eps /*= 0.000001*/)
  931.     int k;
  932.     double xx,yy,a,r,z,x1,y1,z1;
  933. // 求解条件与初值
  934.     a=xStart; 
  935. k=1; 
  936. r=1.0; 
  937. xx=*x; 
  938. yy=*y;
  939.     z=Func(xx,yy);
  940.     
  941. // 精度控制求解
  942. while (a>=eps)
  943.     { 
  944. x1=-a+2.0*a*rnd(&r); 
  945. x1=xx+x1; 
  946.         y1=-a+2.0*a*rnd(&r); 
  947. y1=yy+y1;
  948.         
  949. z1=Func(x1,y1);
  950.         
  951. k=k+1;
  952.         if (z1>=z)
  953.         { 
  954. if (k>nControlB) 
  955. k=1; 
  956. a=a/2.0; 
  957. }
  958. }
  959.         else
  960.         { 
  961. k=1; 
  962. xx=x1; 
  963. yy=y1;  
  964. z=z1;
  965.             if (z<eps)
  966.             { 
  967. *x=xx; 
  968. *y=yy; 
  969. return; 
  970. }
  971.         }
  972.     }
  973.     
  974. *x=xx; 
  975. *y=yy; 
  976. }
  977. //////////////////////////////////////////////////////////////////////
  978. // 求非线性方程组一组实根的梯度法
  979. //
  980. // 调用时,须覆盖计算方程左端函数f(x)值及其偏导数值的虚函数
  981. //         double Func(double x[], double y[])
  982. //
  983. // 参数:
  984. // 1. int n - 方程的个数,也是未知数的个数
  985. // 2. double x[] - 一维数组,长度为n,存放一组初值x0, x1, …, xn-1,
  986. //                 返回时存放方程组的一组实根
  987. // 3. int nMaxIt - 迭代次数,默认值为60
  988. // 4. double eps - 控制精度,默认值为0.000001
  989. //
  990. // 返回值:BOOL 型,求解是否成功
  991. //////////////////////////////////////////////////////////////////////
  992. BOOL CNLequation::GetRootsetGrad(int n, double x[], int nMaxIt /*= 60*/, double eps /*= 0.000001*/)
  993.     int l,j;
  994.     double f,d,s,*y;
  995.     y = new double[n];
  996.     l=nMaxIt;
  997.     f=Func(x,y);
  998. // 控制精度,迭代求解
  999.     while (f>=eps)
  1000.     { 
  1001. l=l-1;
  1002.         if (l==0) 
  1003. delete[] y; 
  1004. return TRUE;
  1005. }
  1006.         
  1007. d=0.0;
  1008.         for (j=0; j<=n-1; j++) 
  1009. d=d+y[j]*y[j];
  1010.         if (d+1.0==1.0) 
  1011. delete[] y; 
  1012. return FALSE;
  1013. }
  1014.         
  1015. s=f/d;
  1016.         for (j=0; j<=n-1; j++) 
  1017. x[j]=x[j]-s*y[j];
  1018.         
  1019. f=Func(x,y);
  1020.     }
  1021.     
  1022. delete[] y; 
  1023. // 是否在有效迭代次数内达到精度
  1024. return (nMaxIt>l);
  1025. }
  1026. //////////////////////////////////////////////////////////////////////
  1027. // 求非线性方程组一组实根的拟牛顿法
  1028. //
  1029. // 调用时,须覆盖计算方程左端函数f(x)值及其偏导数值的虚函数
  1030. //         double Func(double x[], double y[])
  1031. //
  1032. // 参数:
  1033. // 1. int n - 方程的个数,也是未知数的个数
  1034. // 2. double x[] - 一维数组,长度为n,存放一组初值x0, x1, …, xn-1,
  1035. //                 返回时存放方程组的一组实根
  1036. // 3. double t - 控制h大小的变量,0<t<1
  1037. // 4. double h - 增量初值
  1038. // 3. int nMaxIt - 迭代次数,默认值为60
  1039. // 4. double eps - 控制精度,默认值为0.000001
  1040. //
  1041. // 返回值:BOOL 型,求解是否成功
  1042. //////////////////////////////////////////////////////////////////////
  1043. BOOL CNLequation::GetRootsetNewton(int n, double x[], double t, double h, int nMaxIt /*= 60*/, double eps /*= 0.000001*/)
  1044.     int i,j,l;
  1045.     double am,z,beta,d,*y,*a,*b;
  1046.     y = new double[n];
  1047. // 构造矩阵
  1048. CMatrix mtxCoef(n, n);
  1049. CMatrix mtxConst(n, 1);
  1050.     a = mtxCoef.GetData();
  1051.     b = mtxConst.GetData();
  1052. // 迭代求解
  1053.     l=nMaxIt; 
  1054. am=1.0+eps;
  1055.     while (am>=eps)
  1056.     { 
  1057. Func(x,b);
  1058.         
  1059. am=0.0;
  1060.         for (i=0; i<=n-1; i++)
  1061.         { 
  1062. z=fabs(b[i]);
  1063.             if (z>am) 
  1064. am=z;
  1065.         }
  1066.         
  1067. if (am>=eps)
  1068.         { 
  1069. l=l-1;
  1070.             if (l==0)
  1071.             { 
  1072. delete[] y;
  1073.                 return FALSE;
  1074.             }
  1075.             
  1076. for (j=0; j<=n-1; j++)
  1077.             { 
  1078. z=x[j]; 
  1079. x[j]=x[j]+h;
  1080.                 
  1081. Func(x,y);
  1082.                 
  1083. for (i=0; i<=n-1; i++) 
  1084. a[i*n+j]=y[i];
  1085.                 
  1086. x[j]=z;
  1087.             }
  1088.             
  1089. // 调用全选主元高斯消元法
  1090. CLEquations leqs(mtxCoef, mtxConst);
  1091. CMatrix mtxResult;
  1092. if (! leqs.GetRootsetGauss(mtxResult))
  1093. {
  1094. delete[] y;
  1095. return FALSE;
  1096. }
  1097. mtxConst = mtxResult;
  1098. b = mtxConst.GetData();
  1099. beta=1.0;
  1100.             for (i=0; i<=n-1; i++) 
  1101. beta=beta-b[i];
  1102.             
  1103. if (beta == 0.0)
  1104.             { 
  1105. delete[] y;
  1106.                 return FALSE;
  1107.             }
  1108.             
  1109. d=h/beta;
  1110.             for (i=0; i<=n-1; i++) 
  1111. x[i]=x[i]-d*b[i];
  1112.             
  1113. h=t*h;
  1114.         }
  1115.     }
  1116.     
  1117. delete[] y;
  1118.     
  1119. // 是否在有效迭代次数内达到精度
  1120. return (nMaxIt>l);
  1121. }
  1122. //////////////////////////////////////////////////////////////////////
  1123. // 求非线性方程组最小二乘解的广义逆法
  1124. //
  1125. // 调用时,1. 须覆盖计算方程左端函数f(x)值及其偏导数值的虚函数
  1126. //             double Func(double x[], double y[])
  1127. //         2. 须覆盖计算雅可比矩阵函数的虚函数
  1128. //             double FuncMJ(int n, double x[], double y[])
  1129. //
  1130. // 参数:
  1131. // 1. int m - 方程的个数
  1132. // 2. int n - 未知数的个数
  1133. // 3. double x[] - 一维数组,长度为n,存放一组初值x0, x1, …, xn-1,要求
  1134. //                 不全为0,返回时存放方程组的最小二乘解,当m=n时,即是
  1135. //                 非线性方程组的解
  1136. // 4. double eps1 - 最小二乘解的精度控制精度,默认值为0.000001
  1137. // 5. double eps2 - 奇异值分解的精度控制精度,默认值为0.000001
  1138. //
  1139. // 返回值:BOOL 型,求解是否成功
  1140. //////////////////////////////////////////////////////////////////////
  1141. BOOL CNLequation::GetRootsetGinv(int m, int n, double x[], double eps1 /*= 0.000001*/, double eps2 /*= 0.000001*/)
  1142. int i,j,k,l,kk,jt;
  1143.     double y[10],b[10],alpha,z,h2,y1,y2,y3,y0,h1;
  1144.     double *p,*d,*dx,*w;
  1145.     
  1146. // 控制参数
  1147. int ka = max(m, n)+1;
  1148.     w = new double[ka];
  1149.     
  1150. // 设定迭代次数为60,迭代求解
  1151. l=60; 
  1152. alpha=1.0;
  1153.     while (l>0)
  1154.     { 
  1155. CMatrix mtxP(m, n), mtxD(m, 1);
  1156. p = mtxP.GetData();
  1157. d = mtxD.GetData();
  1158. Func(x,d);
  1159.         FuncMJ(n,x,p);
  1160. // 构造线性方程组
  1161. CLEquations leqs(mtxP, mtxD);
  1162. // 临时矩阵
  1163. CMatrix mtxAP, mtxU, mtxV;
  1164. // 解矩阵
  1165. CMatrix mtxDX;
  1166. // 基于广义逆的最小二乘解
  1167. if (! leqs.GetRootsetGinv(mtxDX, mtxAP, mtxU, mtxV, eps2))
  1168.         { 
  1169. delete[] w;
  1170. return FALSE;
  1171.         }
  1172.         
  1173. dx = mtxDX.GetData();
  1174. j=0; 
  1175. jt=1; 
  1176. h2=0.0;
  1177.         while (jt==1)
  1178.         { 
  1179. jt=0;
  1180.             if (j<=2) 
  1181. z=alpha+0.01*j;
  1182.             else 
  1183. z=h2;
  1184.             
  1185. for (i=0; i<=n-1; i++) 
  1186. w[i]=x[i]-z*dx[i];
  1187.             
  1188. Func(w,d);
  1189.             
  1190. y1=0.0;
  1191.             for (i=0; i<=m-1; i++) 
  1192. y1=y1+d[i]*d[i];
  1193.             for (i=0; i<=n-1; i++)
  1194. w[i]=x[i]-(z+0.00001)*dx[i];
  1195.             
  1196. Func(w,d);
  1197.             
  1198. y2=0.0;
  1199.             for (i=0; i<=m-1; i++) 
  1200. y2=y2+d[i]*d[i];
  1201.             
  1202. y0=(y2-y1)/0.00001;
  1203.             
  1204. if (fabs(y0)>1.0e-10)
  1205.             { 
  1206. h1=y0; h2=z;
  1207.                 if (j==0) 
  1208. y[0]=h1; 
  1209. b[0]=h2;
  1210. }
  1211.                 else
  1212.                 { 
  1213. y[j]=h1; 
  1214. kk=0; 
  1215. k=0;
  1216.                     while ((kk==0)&&(k<=j-1))
  1217.                     { 
  1218. y3=h2-b[k];
  1219.                         if (fabs(y3)+1.0==1.0) 
  1220. kk=1;
  1221.                         else 
  1222. h2=(h1-y[k])/y3;
  1223.                         
  1224. k=k+1;
  1225.                     }
  1226.                     
  1227. b[j]=h2;
  1228.                     if (kk!=0) 
  1229. b[j]=1.0e+35;
  1230.                     
  1231. h2=0.0;
  1232.                     for (k=j-1; k>=0; k--)
  1233. h2=-y[k]/(b[k+1]+h2);
  1234.                     
  1235. h2=h2+b[0];
  1236.                 }
  1237.                 
  1238. j=j+1;
  1239.                 if (j<=7) 
  1240. jt=1;
  1241.                 else 
  1242. z=h2;
  1243.             }
  1244.         }
  1245.         
  1246. alpha=z; 
  1247. y1=0.0; 
  1248. y2=0.0;
  1249.         for (i=0; i<=n-1; i++)
  1250.         { 
  1251. dx[i]=-alpha*dx[i];
  1252.             x[i]=x[i]+dx[i];
  1253.             y1=y1+fabs(dx[i]);
  1254.             y2=y2+fabs(x[i]);
  1255.         }
  1256.         
  1257. // 求解成功
  1258. if (y1<eps1*y2)
  1259.         { 
  1260. delete[] w;
  1261. return TRUE;
  1262.         }
  1263.         
  1264. l=l-1;
  1265.     }
  1266.     
  1267. delete[] w;
  1268. // 求解失败
  1269. return FALSE;
  1270. }
  1271. //////////////////////////////////////////////////////////////////////
  1272. // 求非线性方程组一组实根的蒙特卡洛法
  1273. //
  1274. // 调用时,须覆盖计算方程左端模函数值||F||的虚函数
  1275. //         double Func(int n, double x[])
  1276. //         其返回值为Sqr(f1*f1 + f2*f2 + … + fn*fn)
  1277. //
  1278. // 参数:
  1279. // 1. double x[] - 一维数组,长度为n,存放一组初值,返回时存放方程的一组实根
  1280. // 2. double xStart - 均匀分布的端点初值
  1281. // 3. int nControlB - 控制参数
  1282. // 4. double eps - 控制精度,默认值为0.000001
  1283. //
  1284. // 返回值:无
  1285. //////////////////////////////////////////////////////////////////////
  1286. void CNLequation::GetRootsetMonteCarlo(int n, double x[], double xStart, int nControlB, double eps /*= 0.000001*/)
  1287. int k,i;
  1288.     double a,r,*y,z,z1;
  1289.     y = new double[n];
  1290.     
  1291. // 初值
  1292. a=xStart; 
  1293. k=1; 
  1294. r=1.0; 
  1295. z = Func(n, x);
  1296. // 用精度控制迭代求解
  1297.     while (a>=eps)
  1298.     { 
  1299. for (i=0; i<=n-1; i++)
  1300. y[i]=-a+2.0*a*rnd(&r)+x[i];
  1301.         
  1302. z1=Func(n,y);
  1303.         
  1304. k=k+1;
  1305.         if (z1>=z)
  1306.         { 
  1307. if (k>nControlB) 
  1308. k=1; 
  1309. a=a/2.0; 
  1310. }
  1311. }
  1312.         else
  1313.         { 
  1314. k=1; 
  1315.             for (i=0; i<=n-1; i++) 
  1316. x[i]=y[i];
  1317.             
  1318. // 求解成功
  1319. z=z1;
  1320.             if (z<eps)  
  1321. {
  1322. delete[] y;
  1323. return;
  1324. }
  1325.         }
  1326.     }
  1327. delete[] y;
  1328. }