⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nlequation.cpp

📁 科学与工程数值算法求解方程组的类
💻 CPP
📖 第 1 页 / 共 3 页
字号:
					p=u1*x; 
					q=v1*y; 
					pq=(u1+v1)*(x+y);
                    u1=p-q+(k-i+1)*dblCoef[i-1];
                    v1=pq-p-q;
                }
                
				p=u1*u1+v1*v1;
                if (p<=1.0e-20)
                { 
					it=0;
                    g65(&x,&y,&x1,&y1,&dx,&dy,&dd,&dc,&c,&k,&is,&it);
                    if (it==0) 
						goto l40;

                    g90(xr,xi,dblCoef,&x,&y,&p,&q,&w,&k);
                }
                else
                { 
					dx=(u*u1+v*v1)/p;
                    dy=(u1*v-v1*u)/p;
                    t=1.0+4.0/k;
                    g60(&t,&x,&y,&x1,&y1,&dx,&dy,&p,&q,&k,&it);
                    if (t>=1.0e-03) 
						goto l40;

                    if (g>1.0e-18)
                    { 
						it=0;
                        g65(&x,&y,&x1,&y1,&dx,&dy,&dd,&dc,&c,&k,&is,&it);
                        if (it==0) 
							goto l40;
                    }
                    
					g90(xr,xi,dblCoef,&x,&y,&p,&q,&w,&k);
                }
            }
        }
        
		if (k==1) 
			jt=0;
        else 
			jt=1;
    }
    
	return TRUE;
}


//////////////////////////////////////////////////////////////////////
// 内部函数
//////////////////////////////////////////////////////////////////////
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)
{ 
	*it=1;
    while (*it==1)
    { 
		*t=*t/1.67; 
		*it=0;
        *x1=*x-(*t)*(*dx);
        *y1=*y-(*t)*(*dy);
        if (*k>=50)
		{ 
			*p=sqrt((*x1)*(*x1)+(*y1)*(*y1));
            *q=exp(85.0/(*k));
            if (*p>=*q) 
				*it=1;
        }
    }
}

//////////////////////////////////////////////////////////////////////
// 内部函数
//////////////////////////////////////////////////////////////////////
void CNLequation::g90(double xr[],double xi[],double dblCoef[],double* x,double* y,double* p,double* q,double* w,int* k)
{ 
	int i;
    
	if (fabs(*y)<=1.0e-06)
    { 
		*p=-(*x); 
		*y=0.0; 
		*q=0.0;
	}
    else
    { 
		*p=-2.0*(*x); 
		*q=(*x)*(*x)+(*y)*(*y);
        xr[*k-1]=(*x)*(*w);
        xi[*k-1]=-(*y)*(*w);
        *k=*k-1;
    }
    
	for (i=1; i<=*k; i++)
    { 
		dblCoef[i]=dblCoef[i]-dblCoef[i-1]*(*p);
        dblCoef[i+1]=dblCoef[i+1]-dblCoef[i-1]*(*q);
    }
    
	xr[*k-1]=(*x)*(*w); 
	xi[*k-1]=(*y)*(*w);
    *k=*k-1;
    if (*k==1)
    { 
		xr[0]=-dblCoef[1]*(*w)/dblCoef[0]; 
		xi[0]=0.0;
	}
}

//////////////////////////////////////////////////////////////////////
// 内部函数
//////////////////////////////////////////////////////////////////////
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)
{ 
	if (*it==0)
    { 
		*is=1;
        *dd=sqrt((*dx)*(*dx)+(*dy)*(*dy));
        if (*dd>1.0) 
			*dd=1.0;
        *dc=6.28/(4.5*(*k)); 
		*c=0.0;
    }
    
	while(TRUE)
    { 
		*c=*c+(*dc);
        *dx=(*dd)*cos(*c); 
		*dy=(*dd)*sin(*c);
        *x1=*x+*dx; 
		*y1=*y+*dy;
        if (*c<=6.29)
        { 
			*it=0; 
			return;
		}
        
		*dd=*dd/1.67;
        if (*dd<=1.0e-07)
        { 
			*it=1; 
			return;
		}
        
		*c=0.0;
    }
}

//////////////////////////////////////////////////////////////////////
// 求复系数代数方程全部根的牛顿下山法
//
// 参数:
// 1. int n - 多项式方程的次数
// 2. double ar[] - 一维数组,长度为n+1,按降幂次序依次存放n次多项式方程的n+1个系数的实部
// 3. double ai[] - 一维数组,长度为n+1,按降幂次序依次存放n次多项式方程的n+1个系数的虚部
// 4. double xr[] - 一维数组,长度为n,返回n个根的实部
// 5. double xi[] - 一维数组,长度为n,返回n个根的虚部
//
// 返回值:BOOL 型,求解是否成功
//////////////////////////////////////////////////////////////////////
BOOL CNLequation::GetRootNewtonDownHill(int n, double ar[], double ai[], double xr[], double xi[])
{ 
	int m,i,jt,k,is,it;
    double t,x,y,x1,y1,dx,dy,p,q,w,dd,dc,c;
    double g,u,v,pq,g1,u1,v1;

	// 初始判断
    m=n;
    p=sqrt(ar[m]*ar[m]+ai[m]*ai[m]);
    while ((m>0)&&(p+1.0==1.0))
    {  
		m=m-1;
        p=sqrt(ar[m]*ar[m]+ai[m]*ai[m]);
    }
    
	// 求解失败
	if (m<=0)
		return FALSE;

    for (i=0; i<=m; i++)
    { 
		ar[i]=ar[i]/p; 
		ai[i]=ai[i]/p;
	}
    
	for (i=0; i<=m/2; i++)
    { 
		w=ar[i]; 
		ar[i]=ar[m-i]; 
		ar[m-i]=w;
        w=ai[i]; 
		ai[i]=ai[m-i]; 
		ai[m-i]=w;
    }
    
	// 迭代求解
	k=m; 
	is=0; 
	w=1.0;
    jt=1;
    while (jt==1)
    { 
		pq=sqrt(ar[k]*ar[k]+ai[k]*ai[k]);
		while (pq<1.0e-12)
        { 
			xr[k-1]=0.0; 
			xi[k-1]=0.0; 
			k=k-1;
            if (k==1)
            { 
				p=ar[0]*ar[0]+ai[0]*ai[0];
                xr[0]=-w*(ar[0]*ar[1]+ai[0]*ai[1])/p;
                xi[0]=w*(ar[1]*ai[0]-ar[0]*ai[1])/p;
                
				return TRUE;
            }
            
			pq=sqrt(ar[k]*ar[k]+ai[k]*ai[k]);
        }
		
		q=log(pq); 
		q=q/(1.0*k); 
		q=exp(q);
        p=q; 
		w=w*p;
        for (i=1; i<=k; i++)
        { 
			ar[i]=ar[i]/q; 
			ai[i]=ai[i]/q; 
			q=q*p;
		}
        
		x=0.0001; 
		x1=x; 
		y=0.2; 
		y1=y; 
		dx=1.0;
        g=1.0e+37; 
l40:
        u=ar[0]; 
		v=ai[0];
        for (i=1; i<=k; i++)
        { 
			p=u*x1; 
			q=v*y1;
            pq=(u+v)*(x1+y1);
            u=p-q+ar[i]; 
			v=pq-p-q+ai[i];
        }
        
		g1=u*u+v*v;
        if (g1>=g)
        { 
			if (is!=0)
            { 
				it=1;
                g65c(&x,&y,&x1,&y1,&dx,&dy,&dd,&dc,&c,&k,&is,&it);
                if (it==0) 
					goto l40;
            }
            else
            { 
				g60c(&t,&x,&y,&x1,&y1,&dx,&dy,&p,&q,&k,&it);
                if (t>=1.0e-03) 
					goto l40;
                
				if (g>1.0e-18)
                { 
					it=0;
                    g65c(&x,&y,&x1,&y1,&dx,&dy,&dd,&dc,&c,&k,&is,&it);
                    if (it==0) 
						goto l40;
                }
            }
            
			g90c(xr,xi,ar,ai,&x,&y,&p,&w,&k);
        }
        else
        { 
			g=g1; 
			x=x1; 
			y=y1; 
			is=0;
            if (g<=1.0e-22)
				g90c(xr,xi,ar,ai,&x,&y,&p,&w,&k);
            else
            { 
				u1=k*ar[0]; 
				v1=ai[0];
                for (i=2; i<=k; i++)
                { 
					p=u1*x; 
					q=v1*y; 
					pq=(u1+v1)*(x+y);
                    u1=p-q+(k-i+1)*ar[i-1];
                    v1=pq-p-q+(k-i+1)*ai[i-1];
                }
                
				p=u1*u1+v1*v1;
                if (p<=1.0e-20)
                { 
					it=0;
                    g65c(&x,&y,&x1,&y1,&dx,&dy,&dd,&dc,&c,&k,&is,&it);
                    if (it==0) 
						goto l40;
                    
					g90c(xr,xi,ar,ai,&x,&y,&p,&w,&k);
                }
                else
                { 
					dx=(u*u1+v*v1)/p;
                    dy=(u1*v-v1*u)/p;
                    t=1.0+4.0/k;
                    g60c(&t,&x,&y,&x1,&y1,&dx,&dy,&p,&q,&k,&it);
                    if (t>=1.0e-03) 
						goto l40;
                    
					if (g>1.0e-18)
                    { 
						it=0;
                        g65c(&x,&y,&x1,&y1,&dx,&dy,&dd,&dc,&c,&k,&is,&it);
                        if (it==0) 
							goto l40;
                    }
                    
					g90c(xr,xi,ar,ai,&x,&y,&p,&w,&k);
                }
            }
        }
        
		if (k==1) 
			jt=0;
        else 
			jt=1;
    }
    
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// 内部函数
//////////////////////////////////////////////////////////////////////
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)
{ 
	*it=1;
    while (*it==1)
    { 
		*t=*t/1.67; 
		*it=0;
        *x1=*x-*t*(*dx);
        *y1=*y-*t*(*dy);
        if (*k>=30)
		{ 
			*p=sqrt(*x1*(*x1)+*y1*(*y1));
            *q=exp(75.0/(*k));
            if (*p>=*q) 
				*it=1;
        }
    }
}

//////////////////////////////////////////////////////////////////////
// 内部函数
//////////////////////////////////////////////////////////////////////
void CNLequation::g90c(double xr[],double xi[],double ar[],double ai[],double* x,double* y,double* p,double* w,int* k)
{ 
	int i;
    for (i=1; i<=*k; i++)
    { 
		ar[i]=ar[i]+ar[i-1]*(*x)-ai[i-1]*(*y);
        ai[i]=ai[i]+ar[i-1]*(*y)+ai[i-1]*(*x);
    }
    
	xr[*k-1]=*x*(*w); 
	xi[*k-1]=*y*(*w);
    *k=*k-1;
    if (*k==1)
    { 
		*p=ar[0]*ar[0]+ai[0]*ai[0];
        xr[0]=-*w*(ar[0]*ar[1]+ai[0]*ai[1])/(*p);
        xi[0]=*w*(ar[1]*ai[0]-ar[0]*ai[1])/(*p);
    }
}

//////////////////////////////////////////////////////////////////////
// 内部函数
//////////////////////////////////////////////////////////////////////
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)
{ 
	if (*it==0)
    { 
		*is=1;
        *dd=sqrt(*dx*(*dx)+*dy*(*dy));
        if (*dd>1.0) 
			*dd=1.0;
        *dc=6.28/(4.5*(*k)); 
		*c=0.0;
    }
    
	while(TRUE)
    { 
		*c=*c+*dc;
        *dx=*dd*cos(*c); 
		*dy=*dd*sin(*c);
        *x1=*x+*dx; 
		*y1=*y+*dy;
        if (*c<=6.29)
        { 
			*it=0; 
			return;
		}
        
		*dd=*dd/1.67;
        if (*dd<=1.0e-07)
        { 
			*it=1; 
			return;
		}
        
		*c=0.0;
    }
}

//////////////////////////////////////////////////////////////////////
// 求非线性方程一个实根的蒙特卡洛法
//
// 调用时,须覆盖计算方程左端函数f(x)值的虚函数double Func(double x)
//
// 参数:
// 1. double* x - 传入初值(猜测解),返回求得的实根
// 2. double xStart - 均匀分布的端点初值
// 3. int nControlB - 控制参数
// 4. double eps - 控制精度,默认值为0.000001
//
// 返回值:无
//////////////////////////////////////////////////////////////////////
void CNLequation::GetRootMonteCarlo(double* x, double xStart, int nControlB, double eps /*= 0.000001*/)
{ 
	int k;
    double xx,a,y,x1,y1,r;
    
	// 求解条件
	a = xStart; 
	k = 1; 
	r = 1.0;

	// 初值
	xx = *x; 
	y = Func(xx);

	// 精度控制求解
    while (a>=eps)
    { 
		x1=rnd(&r);

		x1=-a+2.0*a*x1;
        x1=xx+x1; 
		y1=Func(x1);
        
		k=k+1;
        if (fabs(y1)>=fabs(y))
        { 
			if (k>nControlB) 
			{ 
				k=1; 
				a=a/2.0; 
			}
		}
        else
        { 
			k=1; 
			xx=x1; 
			y=y1;
            if (fabs(y)<eps)
            { 
				*x=xx; 
				return; 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -