#include<cstdlib>
#include<cmath>
using
namespace
std
#define
N
2
//用来设置方程组的行数
#define
eps
2.2204e-16
double*
MatrixMultiply(double*
J,double
Y[])
double*
Inv(double
*J)
double
norm(double
Q[])
double*
F(double
X[])
double*
JF(double
X[])
int
method(double*
Y,double
epsilon)
int
newdim(double
P[],double
delta,double
epsilon,int
max1,double
*err)
{
double
*Y=NULL,*J=NULL,Q[2]={0},*Z=NULL,*temp=NULL
double
relerr=0.0
int
k=0,i=0,iter=0
Y=F(P)
for(k=1k<max1k++)
{
J=JF(P)
temp=MatrixMultiply(Inv(J),Y)
for(i=0i<Ni++)
Q[i]=P[i]-temp[i]
Z=F(Q)
for(i=0i<Ni++)
temp[i]=Q[i]-P[i]
*err=norm(temp)
relerr=*err/(norm(Q)+eps)
for(i=0i<Ni++)
P[i]=Q[i]
for(i=0i<Ni++)
Y[i]=Z[i]
iter=k
if((*err<delta)||(relerr<delta)||method(Y,epsilon))
break
}
return
iter
}
int
method(double*
Y,double
epsilon)
{
if(fabs(Y[0])<epsilon&&fabs(Y[1])<epsilon)
return
1
else
return
0
}
//矩阵乘法,要求,J为方阵,Y为与J维数相同的列向量
double
*MatrixMultiply(double*
J,double
Y[])
{
double
*X=NULL
int
i=0,j=0
X=(double*)malloc(N*sizeof(double))
for(i=0i<Ni++)
X[i]=0
for(i=0i<Ni++)
for(j=0j<Nj++)
X[i]+=J[i*N+j]*Y[j]
return
X
}
//二阶矩阵的求逆(在M次多项式曲线拟合算法文件中给出了对任意可逆矩阵的求逆算法)
double
*Inv(double
*J)
{
double
X[4]={0},temp=0.0
int
i=0
temp=1/(J[0]*J[3]-J[1]*J[2])
X[0]=J[3]
X[1]=-J[1]
X[2]=-J[2]
X[3]=J[0]
for(i=0i<4i++)
J[i]=temp*X[i]
return
J
}
double
norm(double
Q[])
{
double
max=0.0
int
i=0
for(i=0i<Ni++)
{
if(Q[i]>max)
max=Q[i]
}
return
max
}
double*
F(double
X[])
{
double
x=X[0]
double
y=X[1]
double
*Z=NULL
Z=(double*)malloc(2*sizeof(double))
Z[0]=x*x-2*x-y+0.5
Z[1]=x*x+4*y*y-4
return
Z
}
double*
JF(double
X[])
{
double
x=X[0]
double
y=X[1]
double
*W=NULL
W=(double*)malloc(4*sizeof(double))
W[0]=2*x-2
W[1]=-1
W[2]=2*x
W[3]=8*y
return
W
}
main()
{
double
P[2]={0}
double
delta=0.0,epsilon=0.0,err=0.0
int
max1=0,iter=0,i=0
cout<<"牛顿法解非线性方程组:\nx^2-4-y+2=0\nx^2+4*y^2-2=0\n"
cout<<"\n输入的初始近似值x0,y0\n"
for(i=0i<2i++)
cin>>P[i]
cout<<"请依次输入P的误差限,F(P)的误差限,最大迭代次数\n"
cin>>delta
cin>>epsilon
cin>>err
iter=newdim(P,delta,epsilon,max1,&err)
cout<<"收敛到P的解为:\n"
for(i=0i<2i++)
cout<<"X("<<i+1<<")="<<P[i]<<endl
cout<<"\n迭代次数为:
"<<iter
cout<<"\n."<<err<<endl
getchar()
}
Newton-Raphson 求解非线性方程组matlab源程序matlab程序如下:
function hom
[P,iter,err]=newton('f','JF',[7.8e-0014.9e-0013.7e-001],0.01,0.001,1000)
disp(P)
disp(iter)
disp(err)
function Y=f(x,y,z)
Y=[x^2+y^2+z^2-1
2*x^2+y^2-4*z
3*x^2-4*y+z^2]
function y=JF(x,y,z)
f1='x^2+y^2+z^2-1'
f2='2*x^2+y^2-4*z'
f3='3*x^2-4*y+z^2'
df1x=diff(sym(f1),'x')
df1y=diff(sym(f1),'y')
df1z=diff(sym(f1),'z')
df2x=diff(sym(f2),'x')
df2y=diff(sym(f2),'y')
df2z=diff(sym(f2),'z')
df3x=diff(sym(f3),'x')
df3y=diff(sym(f3),'y')
df3z=diff(sym(f3),'z')
j=[df1x,df1y,df1zdf2x,df2y,df2zdf3x,df3y,df3z]
y=(j)
function [P,iter,err]=newton(F,JF,P,tolp,tolfp,max)
%输入P为初始猜测值,输出P则为近似解
%JF为相应的Jacobian矩阵
%tolp为P的允许误差
%tolfp为f(P)的允许误差
%max:循环次数
Y=f(F,P(1),P(2),P(3))
for k=1:max
J=f(JF,P(1),P(2),P(3))
Q=P-inv(J)*Y
Z=f(F,Q(1),Q(2),Q(3))
err=norm(Q-P)
P=Q
Y=Z
iter=k
if (err<tolp)||(abs(Y)<tolfp||abs(Y)<0.0001)
break
end
end
<pre lang="matlab" line="1" file="test.m">
function homework4
[P,iter,err]=newton('f','JF',[7.8e-0014.9e-0013.7e-001],0.01,0.001,1000)
disp(P)
disp(iter)
disp(err)
function Y=f(x,y,z)
Y=[x^2+y^2+z^2-1
2*x^2+y^2-4*z
3*x^2-4*y+z^2]
function y=JF(x,y,z)
f1='x^2+y^2+z^2-1'
f2='2*x^2+y^2-4*z'
f3='3*x^2-4*y+z^2'
df1x=diff(sym(f1),'x')
df1y=diff(sym(f1),'y')
df1z=diff(sym(f1),'z')
df2x=diff(sym(f2),'x')
df2y=diff(sym(f2),'y')
df2z=diff(sym(f2),'z')
df3x=diff(sym(f3),'x')
df3y=diff(sym(f3),'y')
df3z=diff(sym(f3),'z')
j=[df1x,df1y,df1zdf2x,df2y,df2zdf3x,df3y,df3z]
y=(j)
function [P,iter,err]=newton(F,JF,P,tolp,tolfp,max)
%输入P为初始猜测值,输出P则为近似解
%JF为相应的Jacobian矩阵
%tolp为P的允许误差
%tolfp为f(P)的允许误差
%max:循环次数
Y=f(F,P(1),P(2),P(3))
for k=1:max
J=f(JF,P(1),P(2),P(3))
Q=P-inv(J)*Y
Z=f(F,Q(1),Q(2),Q(3))
err=norm(Q-P)
P=Q
Y=Z
iter=k
if (err<tolp)||(abs(Y)<tolfp||abs(Y)<0.0001)
break
end
牛顿迭代法(Newton's method)又称为牛顿-拉夫逊(拉弗森)方法(Newton-Raphson method),它是牛顿在17世纪提出的一种在实数域和复数域上近似求解方程的方法。中文名
牛顿迭代法
外文名
Newton's method
别名
牛顿-拉夫逊(拉弗森)方法
提出时间
17世纪
快速
导航
牛顿迭代公式
其他迭代算法
C语言代码
C++代码
matlab代码
Python代码
Java代码
JavaScript代码
Fortran代码
产生背景
多数方程不存在求根公式,因此求精确根非常困难,甚至不可解,从而寻找方程的近似根就显得特别重要。方法使用函数 的泰勒级数的前面几项来寻找方程 的根。牛顿迭代法是求方程根的重要方法之一,其最大优点是在方程 的单根附近具有平方收敛,而且该法还可以用来求方程的重根、复根,此时线性收敛,但是可通过一些方法变成超线性收敛。另外该方法广泛用于计算机编程中。
牛顿迭代公式
设 是 的根,选取 作为 的初始近似值,过点 做曲线 的切线 , ,则 与 轴交点的横坐标 ,称 为 的一次近似值。过点 做曲线 的切线,并求该切线与x轴交点的横坐标 ,称 为r的二次近似值。重复以上过程,得 的近似值序列,其中, 称为 的 次近似值,上式称为牛顿迭代公式。
用牛顿迭代法解非线性方程,是把非线性方程 线性化的一种近似方法。把 在点 的某邻域内展开成泰勒级数 ,取其线性部分(即泰勒展开的前两项),并令其等于0,即 ,以此作为非线性方程 的近似方程,若 ,则其解为 , 这样,得到牛顿迭代法的一个迭代关系式: 。
已经证明,如果是连续的,并且待求的零点是孤立的,那么在零点周围存在一个区域,只要初始值位于这个邻近区域内,那么牛顿法必定收敛。 并且,如果不为0, 那么牛顿法将具有平方收敛的性能. 粗略的说,这意味着每迭代一次,牛顿法结果的有效数字将增加一倍。
迭代法也称辗转法,是一种不断用变量的旧值递推新值的过程,跟迭代法相对应的是直接法(或者称为一次解法),即一次性解决问题。迭代算法是用计算机解决问题的一种基本方法。它利用计算机运算速度快、适合做重复性 *** 作的特点,让计算机对一组指令(或一定步骤)重复执行,在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的一个新值。
利用迭代算法解决问题,需要做好以下三个方面的工作:
一、确定迭代变量
在可以用迭代算法解决的问题中,至少存在一个可直接或间接地不断由旧值递推出新值的变量,这个变量就是迭代变量。
二、建立迭代关系式
所谓迭代关系式,指如何从变量的前一个值推出其下一个值的公式(或关系)。迭代关系式的建立是解决迭代问题的关键,通常可以使用递推或倒推的方法来完成。
三、对迭代过程进行控制
在什么时候结束迭代过程?这是编写迭代程序必须考虑的问题。不能让迭代过程无休止地执行下去。迭代过程的控制通常可分为两种情况:一种是所需的迭代次数是个确定的值,可以计算出来;另一种是所需的迭代次数无法确定。对于前一种情况,可以构建一个固定次数的循环来实现对迭代过程的控制;对于后一种情况,需要进一步分析得出可用来结束迭代过程的条件。
其他迭代算法
欧几里德算法
最经典的迭代算法是欧几里德算法,用于计算两个整数a,b的最大公约数。其计算原理依赖于下面的定理:
定理:gcd(a,b) = gcd(b,a mod b)
证明:a可以表示成a = kb + r,则r = a mod b。假设d是a,b的一个公约数,则有 a%d==0,b%d==0,而r = a - kb,因此r%d==0 ,因此d是(b,a mod b)的公约数
查看更多
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)