• 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:
    ");
     27     printMatrix(a, M, M);
     28     printf("
    ");
     29     printf("初始向量u0:
    ");
     30     printVector(uk0, M);
     31     printf("
    ");
     32     printf("第几次计算		 uk				 yk		 βk
    ");
     33     for (int i = 0; i < N; i++)
     34     {
     35         printf("%d	", 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("
    ");
     49         ε = relaError(β0, β1);
     50         //判断是否收敛
     51         if (ε < ε0) //若收敛
     52         {
     53             printf("收敛
    ");
     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("
    ");
     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
    ",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:
    ");
     27     printMatrix(a, M, M);
     28     printf("
    ");
     29     printf("初始向量u0:
    ");
     30     printVector(uk0, M);
     31     printf("
    ");
     32     printf("第几次计算		 uk				 yk		 βk
    ");
     33     for (int i = 0; i < N; i++)
     34     {
     35         printf("%d	", 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("
    ");
     49         ε = relaError(β0, β1);
     50         //判断是否收敛
     51         if (ε < ε0) //若收敛
     52         {
     53             printf("收敛
    ");
     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("
    ");
     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
    ",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)

  • 相关阅读:
    C#类头部声明样式
    VisualStudio使用技巧及快捷键
    #使用ListView更新数据出现闪烁解决办法
    获取公网IP地址
    JArray数组每个JObject对象添加一个键值对
    部署网站出现System.ServiceModel.Activation.HttpModule错误
    MYSQL存储引擎的比较
    数据库索引原理(转载)
    皮尔逊相关系数
    进程与线程
  • 原文地址:https://www.cnblogs.com/zhubinglong/p/5985473.html
Copyright © 2020-2023  润新知