猪冰龙

导航

c语言计算矩阵特征值和特征向量-1(幂法)

  1 #include <stdio.h>
  2 #include <math.h>
  3 #include <stdlib.h>
  4 #define M 3  //方阵的行数 列数
  5 #define ε0  0.00000001//ε0为要求的精度
  6 #define N  100000//最大迭代次数
  7 
  8 //函数预声明
  9 void printMatrix(double a[][3], int m, int n);//矩阵的打印
 10 void printVector(double a[], int m);//向量的打印
 11 double dotVector(double a[], double b[], int m);//两个一维向量之积,结果为一个数
 12 void dotMatrVect(double a[][3], double yk0[], double uk1[], int m);//矩阵和向量点积u=a.*y,yk0对应于书上y(k-1)
 13 void unitVector(double a[], int η, int m);//向量的单位化
 14 double relaError(double lamada1, double lamada2);//计算相对误差
 15 
 16 //主函数
 17 int main(void)
 18 {
 19     double a[M][M] = { { 6, -12, 6 }, { -21, -3, 24 }, { -12, -12, 51 } };//待求特征值和特征向量的矩阵
 20     double uk0[M] = { 1.0, 0.0, 0.0 };//迭代向量
 21     double uk1[M] = { 0.0, 0.0, 0.0 };//迭代向量
 22     double β0 = 0.0;//β(k-1)
 23     double β1 = 0.0;//βk
 24     double η0 = 0.0;//向量u(k-1)的二范数
 25     double ε = 0.0;//计算的精度
 26     printf("待求特征值和特征向量的矩阵A:\n");
 27     printMatrix(a, M, M);
 28     printf("\n");
 29     printf("初始向量u0:\n");
 30     printVector(uk0, M);
 31     printf("\n");
 32     printf("第几次计算\t\t uk\t\t\t\t yk\t\t βk\n");
 33     for (int i = 0; i < N; i++)
 34     {
 35         printf("%d\t", i);//***打印计算次数i
 36         printVector(uk0, M);//***打印uk
 37         printf("|");//***打印分隔
 38         η0 = sqrt(dotVector(uk0, uk0, M));//初始向量u0的2范数
 39         unitVector(uk0, η0, M);//将初始向量u0单位化作为y(k-1)也就是yk0
 40         printVector(uk0, M); //***打印单位化后的uk0,也就是y(k-1)
 41         dotMatrVect(a, uk0, uk1, M);//uk1 = A.*yk0;
 42         printf("|");//***打印分隔
 43         β1 = dotVector(uk0, uk1, M);//β1=y(k-1).*uk1
 44         if (i>0)
 45         {
 46             printf("%lf ", β1);//***打印βk
 47         }
 48         printf("\n");
 49         ε = relaError(β0, β1);
 50         //判断是否收敛
 51         if (ε < ε0) //若收敛
 52         {
 53             printf("收敛\n");
 54             break;
 55         }
 56         else //若不收敛,则变量交换 uk0=uk1;
 57         {
 58             //double tem = 0.0;
 59             for (int q = 0; q < M; q++)
 60             {
 61                 //uk0[q] = uk1[q];
 62                 //tem = uk0[q];
 63                 uk0[q] = uk1[q];
 64                 uk1[q] = 0.0;//在第二次使用前一定把uk1[i]的所有元素归零!!!!!!
 65             }
 66             β0 = β1;
 67         }
 68     }
 69 
 70     system("pause");
 71 }
 72 
 73 //函数具体执行
 74 
 75 //矩阵的打印
 76 void printMatrix(double a[][M], int m, int n)
 77 {
 78     for (int i = 0; i<m; i++)
 79     {
 80         for (int j = 0; j<n; j++)
 81         {
 82             printf("%lf  ", a[i][j]);
 83         }
 84         printf("\n");
 85     }
 86 }
 87 //向量的打印
 88 void printVector(double a[], int m)
 89 {
 90     for (int i = 0; i < m; i++)
 91     {
 92         printf("%lf  ", a[i]);
 93     }
 94 }
 95 //两个一维向量之积
 96 double dotVector(double a[], double b[], int m)
 97 {
 98     double dotsum = 0.0;
 99     for (int i = 0; i < m; i++)
100     {
101         dotsum = dotsum + a[i] * b[i];
102     }
103     return(dotsum);
104 }
105 //矩阵和向量点积u=a.*y,yk0对应于书上y(k-1)
106 void dotMatrVect(double a[][M], double yk0[], double uk1[], int m)
107 {
108     double a1, b, c;
109     for (int i = 0; i < m; i++)
110     {
111         uk1[i] = 0;//在第二次使用前一定把uk1[i]的所有元素归零!!!!!!
112         for (int j = 0; j < m; j++)
113         {
114             uk1[i] = uk1[i] + a[i][j] * yk0[j];//在第二次使用前一定把uk1[i]的所有元素归零!!!!!!!!!
115             a1 = a[i][j];
116             b = yk0[j];
117             c = uk1[i];
118             //printf("a[%d][%d]=%lf\n",i,j,a[i][j]);
119         }
120 
121     }
122     //printVector(uk1, 3);
123 }
124 //向量的单位化
125 void unitVector(double a[], int η, int m)
126 {
127     for (int i = 0; i < m; i++)
128     {
129         a[i] = a[i] / η;
130     }
131 }
132 //计算误差
133 double relaError(double β1, double β2)
134 {
135     double ε;
136     ε = fabs(β2 - β1) / fabs(β2);
137     return ε;
138 }

 为啥上面的总是算的不是太精确呢??

奥,因为二范数取的是int类型;

  1 #include <stdio.h>
  2 #include <math.h>
  3 #include <stdlib.h>
  4 #define M 3  //方阵的行数 列数
  5 #define ε0  0.00000001//ε0为要求的精度
  6 #define N  100000//最大迭代次数
  7 
  8 //函数预声明
  9 void printMatrix(double a[][3], int m, int n);//矩阵的打印
 10 void printVector(double a[], int m);//向量的打印
 11 double dotVector(double a[], double b[], int m);//两个一维向量之积,结果为一个数
 12 void dotMatrVect(double a[][3], double yk0[], double uk1[], int m);//矩阵和向量点积u=a.*y,yk0对应于书上y(k-1)
 13 void unitVector(double a[], double η, int m);//向量的单位化
 14 double relaError(double lamada1, double lamada2);//计算相对误差
 15 
 16 //主函数
 17 int main(void)
 18 {
 19     double a[M][M] = { { 6, -12, 6 }, { -21, -3, 24 }, { -12, -12, 51 } };//待求特征值和特征向量的矩阵
 20     double uk0[M] = { 2.0, 1.0, 6.0 };//迭代向量
 21     double uk1[M] = { 0.0, 0.0, 0.0 };//迭代向量
 22     double β0 = 0.0;//β(k-1)
 23     double β1 = 0.0;//βk
 24     double η0 = 0.0;//向量u(k-1)的二范数
 25     double ε = 0.0;//计算的精度
 26     printf("待求特征值和特征向量的矩阵A:\n");
 27     printMatrix(a, M, M);
 28     printf("\n");
 29     printf("初始向量u0:\n");
 30     printVector(uk0, M);
 31     printf("\n");
 32     printf("第几次计算\t\t uk\t\t\t\t yk\t\t βk\n");
 33     for (int i = 0; i < N; i++)
 34     {
 35         printf("%d\t", i);//***打印计算次数i
 36         printVector(uk0, M);//***打印uk
 37         printf("|");//***打印分隔
 38         η0 = sqrt(dotVector(uk0, uk0, M));//初始向量u0的2范数
 39         unitVector(uk0, η0, M);//将初始向量u0单位化作为y(k-1)也就是yk0
 40         printVector(uk0, M); //***打印单位化后的uk0,也就是y(k-1)
 41         dotMatrVect(a, uk0, uk1, M);//uk1 = A.*yk0;
 42         printf("|");//***打印分隔
 43         β1 = dotVector(uk0, uk1, M);//β1=y(k-1).*uk1
 44         if (i>0)
 45         {
 46             printf("%lf ", β1);//***打印βk
 47         }
 48         printf("\n");
 49         ε = relaError(β0, β1);
 50         //判断是否收敛
 51         if (ε < ε0) //若收敛
 52         {
 53             printf("收敛\n");
 54             break;
 55         }
 56         else //若不收敛,则变量交换 uk0=uk1;
 57         {
 58             //double tem = 0.0;
 59             for (int q = 0; q < M; q++)
 60             {
 61                 //uk0[q] = uk1[q];
 62                 //tem = uk0[q];
 63                 uk0[q] = uk1[q];
 64                 uk1[q] = 0.0;//在第二次使用前一定把uk1[i]的所有元素归零!!!!!!
 65             }
 66             β0 = β1;
 67         }
 68     }
 69 
 70     system("pause");
 71 }
 72 
 73 //函数具体执行
 74 
 75 //矩阵的打印
 76 void printMatrix(double a[][M], int m, int n)
 77 {
 78     for (int i = 0; i<m; i++)
 79     {
 80         for (int j = 0; j<n; j++)
 81         {
 82             printf("%lf  ", a[i][j]);
 83         }
 84         printf("\n");
 85     }
 86 }
 87 //向量的打印
 88 void printVector(double a[], int m)
 89 {
 90     for (int i = 0; i < m; i++)
 91     {
 92         printf("%lf  ", a[i]);
 93     }
 94 }
 95 //两个一维向量之积
 96 double dotVector(double a[], double b[], int m)
 97 {
 98     double dotsum = 0.0;
 99     for (int i = 0; i < m; i++)
100     {
101         dotsum = dotsum + a[i] * b[i];
102     }
103     return(dotsum);
104 }
105 //矩阵和向量点积u=a.*y,yk0对应于书上y(k-1)
106 void dotMatrVect(double a[][M], double yk0[], double uk1[], int m)
107 {
108     double a1, b, c;
109     for (int i = 0; i < m; i++)
110     {
111         uk1[i] = 0;//在第二次使用前一定把uk1[i]的所有元素归零!!!!!!
112         for (int j = 0; j < m; j++)
113         {
114             uk1[i] = uk1[i] + a[i][j] * yk0[j];//在第二次使用前一定把uk1[i]的所有元素归零!!!!!!!!!
115             a1 = a[i][j];
116             b = yk0[j];
117             c = uk1[i];
118             //printf("a[%d][%d]=%lf\n",i,j,a[i][j]);
119         }
120 
121     }
122     //printVector(uk1, 3);
123 }
124 //向量的单位化
125 void unitVector(double a[], double η, int m)
126 {
127     for (int i = 0; i < m; i++)
128     {
129         a[i] = a[i] / η;
130     }
131 }
132 //计算误差
133 double relaError(double β1, double β2)
134 {
135     double ε;
136     ε = fabs(β2 - β1) / fabs(β2);
137     return ε;
138 }

精确结果是 绝对值最大的特征值为45,对应的特征向量为(0,-0.5,-1)

 

posted on 2016-10-21 17:32  猪冰龙  阅读(4617)  评论(0编辑  收藏  举报