计算实习报告
姓名:涂高波
姓名:林鑫
姓名:张庆
姓名:赵海洲
学号:2007302490 班级:11010701
学号:
学号:
学号:
班级:
班级:
班级:
一 实习目的
(1)了解矩阵特征值与相应特征向量求解的意义,理解幂法和反幂法的原理,
能编制此算法的程序,并能求解实际问题。
(2)通过对比非线性方程的迭代法,理解线性方程组迭代解法的原理,学会编
写Jacobi 迭代法程序,并能求解中小型非线性方程组。初始点对收敛性质及收
敛速度的影响。
(3)理解 QR 法计算矩阵特征值与特征向量的原理,能编制此算法的程序,并
用于实际问题的求解。
二 问题定义及题目分析
1. 分别用幂法和幂法加速技术求矩阵
2.5
0.0
0.5
2.5
A
2.5
5.0
0.5
2.5
0.5
3.0
2.0 2.0
2.5
4.0
5.0
3.5
的主特征值和特征向量.
2. 对于实对称矩阵
n nA R ,用 Jacobi 方法编写其程序,并用所编程序求下列矩阵的全部
特征值.
4
1
1
4
1
1
4
A
4
1
1
4
1
1
4
15 15
1
n nA R ,用 QR 方法编写其程序,并用所编程序求下列矩阵的全部特征值:
3. 对于实矩阵
1
1
2
n
1
1
3
n
1
1
n
3,4,5,6
1
2
1
n
n
A
n
1
1
三 概要设计
(1) 幂法用于求按模最大的特征值及其对应的特征向量的一种数值算法,
它要求矩阵 A的特征值有如下关系: 1
2
...
n
,对于相应
的特征向量。其算法如下:
,
Step 0:初始化数据
k
1 .
k
Step 1:计算
y
m
Step 2:令 k
z
Step 3:令 k
。
1
0
,
A z
A z
k
y
k
y m
k
k
。
;如果
m m
1
k
k
或
z
k
z
1
k
,则 goto
Step 4;否则 , k = k + 1 ,goto Step 1。
Step 4:输出结果
算法说明与要求
输入参数为实数矩阵、初始向量、误差限与最大迭代次数。输出
参数为特征值及相对应的特征向量。注意初始向量不能为“0”向量。
(2) 迭代法的原理
如果能将方程 Ax=b 改写成等价形式:x=Bx+f。如果B 满足:ρ(B)<1,
则对于任意初始向量 x (0) ,由迭代 x( k + 1) = Bx(k ) + f 产生的序列均
收敛到方程组的精确解。迭代法中两种最有名的迭代法就是Jacobi 迭代法,它
的迭代矩阵 B 为:
D L U
1
f D b
1(
J
)
,
其中,D 为系数矩阵 A 的对角元所组成对角矩阵,L 为系数矩阵 A 的对角元下
方所有元素所组成的下三角矩阵,U 为系数矩阵 A 的对角元上方所有元素所组
成的上三角矩阵。
算法如下:
Step 0:初始化数据
k
0,
,
A b x
,
,
0
和 。
Step 1:计算D,L,U,J或G, 得到迭代矩阵B.
f
Step 2: :
k
1
k
x B x
0
x
x
0
x
Step 2。
Step 3:输出结果。
如果
x
0
或
f x ,goto Step 3;否则 goto
程序说明与要求
程序的输入参数为系数矩阵与常量、初始向量及误差控制,输出参数
为方程组的近似解。要求输入系数 A 中对角元不能存在 0,如果对角元出
现 0 元素,则可以通过交换方程组中方程的次序解决。
(3) QR法原理
QR算法是求实对称矩阵全部特征的最有效方法。其基本过程就是利用矩
阵的QR分解,即将任一实数矩阵分解为一个正交矩阵Q 与一个上三角矩
阵 R 的乘积。
QR 算法的计算过程如下
Step 0:初始化数据
A Q R
,
,
0
,
A
0
Q R k
,
0
0
1
Step 1:令
A
k
Q
R
1
k
k
1
。
A
Step 2:计算 k
Step 3:令 km 为 kR 所有对角元下方元素绝对值之和;
Q R
k
k
如果 km ,则 goto Step 4;
否则, k = k + 1 ,goto Step 1。
Step 4:输出结果。
算法的要求与说明
先利用函数 house 将对称矩阵 A 通过Householder 相似变换为对
称三对角阵 T,然后通过程序 QR_method 求出矩阵 T 的特征值。程序
输入参数为矩阵 A,输出参数为矩阵 A 的所有特征值。
四 详细设计
源程序
(1)
#include"math.h"
#include"stdio.h"
void main()
{int i,j;
int n=4,k=0;
float
/*主函数*/
a[4][4]={{2.5,-2.5,3.0,0.5},{0.0,5.0,-2.0,2.0},{-0.5,-0.5,4.0,2.5},{-2.
5,-2.5,5.0,3.5}},x[4]={1,1,1,1};
double max,m,y[4],z[4],ej=0.0001,e;
printf("k
max(xk)
y(k)=x(k)/max(x(k))
x(k+1)=a*y(k)\n");
/*输出格式*/
cyclo:
{for(i=0;i
max)
max=fabs(x[i]);
}
for(i=0;iej) goto cyclo;
else
{printf("at last %f
",max);
/*输出循环中止时的最终结果,即矩阵
的主特征值和对应的特征向量y[]*/
printf("(");
for(i=0;i}
(2)
#include
#include
//a 存放n阶实对称阵,返回时对角线存放n个特征值
//n 矩阵阶数
//v
//eps 控制精度
//jt 最大迭代次数
n阶矩阵,第j列为对应第j个特征值的特征向量
//返回值:大于0则计算成功,小于0则失败
int jacobi(double *a,int n,double *v,double eps,int jt)
{
int i,j,p,q,u,w,t,s,l;
double fm,cn,sn,omega,x,y,d;
l=1;
for (i=0; i<=n-1; i++)
{ v[i*n+i]=1.0;
for (j=0; j<=n-1; j++)
if (i!=j) v[i*n+j]=0.0;
}
while (1)
{ fm=0.0;
for (i=1; i<=n-1; i++)
for (j=0; j<=i-1; j++)
{ d=fabs(a[i*n+j]);
if ((i!=j)&&(d>fm))
{ fm=d; p=i; q=j;}
}
if (fmjt) return(-1);
l=l+1;
u=p*n+q; w=p*n+p; t=q*n+p; s=q*n+q;
x=-a[u]; y=(a[s]-a[w])/2.0;
omega=x/sqrt(x*x+y*y);
if (y<0.0) omega=-omega;
sn=1.0+sqrt(1.0-omega*omega);
sn=omega/sqrt(2.0*sn);
cn=sqrt(1.0-sn*sn);
fm=a[w];
a[w]=fm*cn*cn+a[s]*sn*sn+a[u]*omega;
a[s]=fm*sn*sn+a[s]*cn*cn-a[u]*omega;
a[u]=0.0; a[t]=0.0;
for (j=0; j<=n-1; j++)
if ((j!=p)&&(j!=q))
{ u=p*n+j; w=q*n+j;
fm=a[u];
a[u]=fm*cn+a[w]*sn;
a[w]=-fm*sn+a[w]*cn;
}
for (i=0; i<=n-1; i++)
if ((i!=p)&&(i!=q))
{ u=i*n+p; w=i*n+q;
fm=a[u];
a[u]=fm*cn+a[w]*sn;
a[w]=-fm*sn+a[w]*cn;
}
for (i=0; i<=n-1; i++)
{ u=i*n+p; w=i*n+q;
fm=v[u];
v[u]=fm*cn+v[w]*sn;
v[w]=-fm*sn+v[w]*cn;
}
}
return(1);
}
int main(){
int i,j;
double a[15][15];
double v[15][15];
printf("示例矩阵:\n");
for(i=0;i<=14;i++)
{
for(j=0;j<=14;j++)
{
if(i==j)
a[i][j]=4;
else if(fabs(i-j)==1)
a[i][j]=-1;
else
a[i][j]=0;
printf("%lf\t",a[i][j]);
}
printf("\n");
}
jacobi((double*)a,15,(double*)v,0.0001,100);
for(i=0;i<=14;i++)
{printf("特征值为:%lf\t",a[i][i]);}
return 0;
}
(3)
#include
#include
#include
using namespace std;
#include
#define N 3 //矩阵的维数
#define NUM 15 //QR分解次数
#define SNUM 13 //用来控制输出格式
void Print(long double A[N][N],long double Q[N][N],long double R[N][N]);
//矩阵输出
void QR(long double A[N][N],long double Q[N][N],long double R[N][N]);
//QR分解
void Multiplicate(long double A[N][N],long double R[N][N],long double
Q[N][N]);
//迭代,获得下一次矩阵A=QR
int main()
{
int i,j;
long double A[N][N];
long double Q[N][N]={0};
long double R[N][N]={0};
cout<<"*************************************************************"<<
endl;
cout<<"输入初始矩阵:\n";
cout<<"-------------------------------------------------------------"<<
endl;
for(i=0;i>A[i][j];
cout<<"*************************************************************"<<
endl;
cout<<"输出每一步迭代过程: \n";
cout<<"*************************************************************"<<
endl;
for(i=1;i<=NUM;i++)
{
QR(A,Q,R);
cout<<"第"<