实对称矩阵特征值特征向量求解算法C语言实现

article/2025/9/28 20:24:43

一 算法原理

雅可比方法用于求解实对称矩阵的特征值和特征向量,对于实对称矩阵 A A A,必有正交矩阵 U U U,使得 U T A U = D U^{T}AU=D UTAU=D. D D D是一个对角阵,主对角线的元素是矩阵 A A A的特征值,正交矩阵 U U U的每一列对应于属于矩阵 D D D的主对角线对应元素的特征向量.
雅可比方法用平面旋转对矩阵 A A A做相似变换,化 A A A为对角阵,从而求解出特征值和特征向量.旋转矩阵 U p q U_p{_q} Upq,是一个单位阵在第 p p p行,第 p p p列,第 q q q行,第 q q q列,元素为 c o s φ cos\varphi cosφ,第 p p p行第 q q q列为 − s i n φ -sin\varphi sinφ,第 q q q行第 p p p列为 s i n φ sin\varphi sinφ.对于这样的平面旋转矩阵,不难验证其是一种正交矩阵.因此对于向量 x x x, U p q x U_p{_q}x Upqx等同于把第 p p p个坐标轴和第 q q q个坐标轴共同所确定的平面旋转了 φ \varphi φ度.记矩阵 A 1 = U p q T A U p q A_1=U_p{_q}^{T}AU_p{_q} A1=UpqTAUpq.因为旋转矩阵是正交阵,因此实际上矩阵 A 1 A_1 A1与矩阵 A A A是相似的,因此其特征值是相同的.
设矩阵 A 1 A_1 A1 i i i行,第 j j j列的元素为 b i j b_i{_j} bij,矩阵 A A A的第 i i i行,第 j j j列的元素为 a i j a_i{_j} aij( i = 0 , 1 , 2 , . . . , n − 1 , j = 0 , 1 , 2 , . . . , n − 1 i=0,1,2,...,n-1,j=0,1,2,...,n-1 i=0,1,2,...,n1,j=0,1,2,...,n1).式(1-1-1)给出了两矩阵元素之间的运算关系.
{ b p p = a p p c o s 2 φ + a q q s i n 2 φ + 2 a p q c o s φ s i n φ b q q = a p p s i n 2 φ + a q q c o s 2 φ − 2 a p q c o s φ s i n φ b p q = b q p = 1 2 ( a q q − a p p ) s i n 2 φ + a p q c o s 2 φ b p i = a p i c o s φ + a q i s i n φ , ( i ≠ p , q ) b q i = − a p i s i n φ + a q i c o s φ , ( i ≠ p , q ) b j p = a j p c o s φ + a j q s i n φ , ( j ≠ p , q ) b j q = − a j q s i n φ + a j q c o s φ , ( j ≠ p , q ) b i j = b j i = a i j , i ≠ p , q ; j ≠ p , q (1-1-1) \begin{cases} b_p{_p}=a_p{_p}cos^2\varphi+a_q{_q}sin^2\varphi+2a_p{_q}cos\varphi{sin\varphi}\\ b_q{_q}=a_p{_p}sin^2\varphi+a_q{_q}cos^2\varphi-2a_p{_q}cos\varphi{sin\varphi}\\ b_p{_q}=b_q{_p}=\frac{1}2(a_q{_q}-a_p{_p})sin2\varphi+a_p{_q}cos2\varphi\\ b_p{_i}=a_p{_i}cos\varphi+a_q{_i}sin\varphi,(i\ne{p},q)\\ b_q{_i}=-a_p{_i}sin\varphi+a_q{_i}cos\varphi,(i\ne{p},q)\\ b_j{_p}=a_j{_p}cos\varphi+a_j{_q}sin\varphi,(j\ne{p},q)\\ b_j{_q}=-a_j{_q}sin\varphi+a_j{_q}cos\varphi,(j\ne{p},q)\\ b_i{_j}=b_j{_i}=a_i{_j},i{\ne}p,q;j{\ne}p,q \end{cases} \tag{1-1-1} bpp=appcos2φ+aqqsin2φ+2apqcosφsinφbqq=appsin2φ+aqqcos2φ2apqcosφsinφbpq=bqp=21(aqqapp)sin2φ+apqcos2φbpi=apicosφ+aqisinφ,(i=p,q)bqi=apisinφ+aqicosφ,(i=p,q)bjp=ajpcosφ+ajqsinφ,(j=p,q)bjq=ajqsinφ+ajqcosφ,(j=p,q)bij=bji=aij,i=p,q;j=p,q(1-1-1)
其中有两点需要说明:(1) p p p, q q q分别是前一次的迭代矩阵的非主对角线上绝对值最大元素的行列号
(2) φ \varphi φ是旋转角度,可以由式(1-1-2)确定
t a n 2 φ = − 2 a p q a q q − a p p (1-1-2) tan2\varphi=\frac{-2a_p{_q}}{a_q{_q}-a_p{_p}} \tag{1-1-2} tan2φ=aqqapp2apq(1-1-2)
归纳得到雅可比方法求解矩阵特征值和特征向量的具体步骤如下:
(1).初始化特征向量为对角阵V,主对角线元素为1,其他元素为0.
(2).在 A A A的非主对角线的元素中,找到绝对值最大元素 a p q a_p{_q} apq.
(3).用式(1-1-2)计算出旋转矩阵
(4).计算矩阵 A 1 A1 A1,用当前的矩阵 V V V乘旋转矩阵得到当前的特征矩阵 V V V.
(5).若当前迭代的矩阵 A A A的非主对角线元素最大值小于给定阈值,停止计算,否则执行上述过程.停止计算时,特征值为矩阵 A A A的主对角线元素,特征矩阵为矩阵 V V V.


二 C语言实现

#include<stdio.h>
#include<stdlib.h>
float** Matrix_Jac_Eig(float **array, int n, float *eig);
int Matrix_Free(float **tmp, int m, int n);
int main(void)
{int n;printf("请输入矩阵维度:\n");scanf("%d", &n);float **array = (float **)malloc(n * sizeof(float *));if (array == NULL){printf("error :申请数组内存空间失败\n");return -1;}for (int i = 0; i < n; i++){array[i] = (float *)malloc(n * sizeof(float));if (array[i] == NULL){printf("error :申请数组子内存空间失败\n");return -1;}}printf("请输入矩阵元素:\n");for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){scanf("%f", &array[i][j]);}}float *eig = (float *)malloc(n * sizeof(float));float **Result = Matrix_Jac_Eig(array, n, eig);printf("特征矩阵元素:\n");for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){printf("%f ", Result[i][j]);}printf("\n");}printf("特征矩阵元素:\n");for (int i = 0; i < n; i++){printf("%f \n", eig[i]);}Matrix_Free(Result, n, n);free(eig);eig = NULL;return 0;
}
float** Matrix_Jac_Eig(float **array, int n, float *eig)
{//先copy一份array在temp_mat中,因为我实在堆区申请的空间,在对其进行处理//的过程中会修改原矩阵的值,因此要存储起来,到最后函数返回的//时候再重新赋值int i, j, flag, k;flag = 0;k = 0;float sum = 0;float **temp_mat = (float **)malloc(n * sizeof(float *));for (i = 0; i < n; i++){temp_mat[i] = (float *)malloc(n * sizeof(float));}for (i = 0; i < n; i++){for (j = 0; j < n; j++){temp_mat[i][j] = array[i][j];}}//判断是否为对称矩阵for (i = 0; i < n; i++){for (j = i; j < n; j++){if (array[i][j] != array[j][i]){flag = 1;break;}}}if (flag == 1){printf("error in Matrix_Eig: 输入并非是对称矩阵:\n");return NULL;}else{//开始执行算法int p, q;float thresh = 0.0000000001;float max = array[0][1];float tan_angle, sin_angle, cos_angle;float **result = (float **)malloc(n * sizeof(float *));if (result == NULL){printf("error in Matrix_Eig:申请空间失败\n");return NULL;}float **result_temp = (float **)malloc(n * sizeof(float *));if (result_temp == NULL){printf("error in Matrix_Eig:申请空间失败\n");return NULL;}float **rot = (float **)malloc(n * sizeof(float *));if (rot == NULL){printf("error in Matrix_Eig:申请空间失败\n");return NULL;}float **mat = (float **)malloc(n * sizeof(float *));if (mat == NULL){printf("error in Matrix_Eig:申请空间失败\n");return NULL;}for (i = 0; i < n; i++){result[i] = (float *)malloc(n * sizeof(float));if (result[i] == NULL){printf("error in Matrix_Eig:申请子空间失败\n");return NULL;}result_temp[i] = (float *)malloc(n * sizeof(float));if (result_temp[i] == NULL){printf("error in Matrix_Eig:申请子空间失败\n");return NULL;}rot[i] = (float *)malloc(n * sizeof(float));if (rot[i] == NULL){printf("error in Matrix_Eig:申请子空间失败\n");return NULL;}mat[i] = (float *)malloc(n * sizeof(float));if (mat[i] == NULL){printf("error in Matrix_Eig:申请子空间失败\n");return NULL;}}for (i = 0; i < n; i++){for (j = 0; j < n; j++){if (i == j){result[i][j] = 1;}else{result[i][j] = 0;}}}for (i = 0; i < n; i++){for (j = 0; j < n; j++){if (i == j){mat[i][j] = 1;}else{mat[i][j] = 0;}}}max = array[0][1];for (i = 0; i < n; i++){for (j = 0; j < n; j++){if (i == j){continue;}else{if (fabs(array[i][j]) >= fabs(max)){max = array[i][j];p = i;q = j;}else{continue;}}}}while (fabs(max) > thresh){if (fabs(max) < thresh){break;}tan_angle = -2 * array[p][q] / (array[q][q] - array[p][p]);sin_angle = sin(0.5*atan(tan_angle));cos_angle = cos(0.5*atan(tan_angle));for (i = 0; i < n; i++){for (j = 0; j < n; j++){if (i == j){mat[i][j] = 1;}else{mat[i][j] = 0;}}}mat[p][p] = cos_angle;mat[q][q] = cos_angle;mat[q][p] = sin_angle;mat[p][q] = -sin_angle;for (i = 0; i < n; i++){for (j = 0; j < n; j++){rot[i][j] = array[i][j];}}for (j = 0; j < n; j++){rot[p][j] = cos_angle*array[p][j] + sin_angle*array[q][j];rot[q][j] = -sin_angle*array[p][j] + cos_angle*array[q][j];rot[j][p] = cos_angle*array[j][p] + sin_angle*array[j][q];rot[j][q] = -sin_angle*array[j][p] + cos_angle*array[j][q];}rot[p][p] = array[p][p] * cos_angle*cos_angle +array[q][q] * sin_angle*sin_angle +2 * array[p][q] * cos_angle*sin_angle;rot[q][q] = array[q][q] * cos_angle*cos_angle +array[p][p] * sin_angle*sin_angle -2 * array[p][q] * cos_angle*sin_angle;rot[p][q] = 0.5*(array[q][q] - array[p][p]) * 2 * sin_angle*cos_angle +array[p][q] * (2 * cos_angle*cos_angle - 1);rot[q][p] = 0.5*(array[q][q] - array[p][p]) * 2 * sin_angle*cos_angle +array[p][q] * (2 * cos_angle*cos_angle - 1);for (i = 0; i < n; i++){for (j = 0; j < n; j++){array[i][j] = rot[i][j];}}max = array[0][1];for (i = 0; i < n; i++){for (j = 0; j < n; j++){if (i == j){continue;}else{if (fabs(array[i][j]) >= fabs(max)){max = array[i][j];p = i;q = j;}else{continue;}}}}for (i = 0; i < n; i++){eig[i] = array[i][i];}for (i = 0; i < n; i++){for (j = 0; j < n; j++){sum = 0;for (k = 0; k < n; k++){sum = sum + result[i][k] * mat[k][j];}result_temp[i][j] = sum;}}for (i = 0; i < n; i++){for (j = 0; j < n; j++){result[i][j] = result_temp[i][j];}}}for (i = 0; i < n; i++){for (j = 0; j < n; j++){array[i][j] = temp_mat[i][j];}}Matrix_Free(result_temp, n, n);Matrix_Free(rot, n, n);Matrix_Free(mat, n, n);Matrix_Free(temp_mat, n, n);return result;}
}
int Matrix_Free(float **tmp, int m, int n)
{int i, j;if (tmp == NULL){return(1);}for (i = 0; i < m; i++){if (tmp[i] != NULL){free(tmp[i]);tmp[i] = NULL;}}if (tmp != NULL){free(tmp);tmp = NULL;}return(0);
}

三 结果

在这里插入图片描述


http://chatgpt.dhexx.cn/article/X1v1Zojt.shtml

相关文章

【矩阵论】对称矩阵特征值的性质与直积

前言 在许多实际问题中&#xff0c;所产生的矩阵往往都是对称矩阵&#xff0c;比如我们耳熟能详的实对称矩阵也是重要的研究对象。以下就从实对称矩阵的角度出发&#xff0c;利用特征值的极小极大原理&#xff0c;从普通特征值问题 A x λ x Ax\lambda x Axλx衍生到广义特征…

对称矩阵的特征值与特征向量

对称矩阵&#xff1a; A A的转置 这里讨论的是实对称矩阵 两个好的性质&#xff1a; 1&#xff0c; 特征值是实数 2&#xff0c;特征向量是两两正交的 一个对称矩阵A可以进行如下分解&#xff1a; AQQ的转置 对于对称矩阵来说&#xff0c;有一个性质&#xff1a;主元的符…

【Java】 IDEA使用教程

前言&#xff1a;IntelliJ IDEA 如果说IntelliJ IDEA是一款现代化智能开发工具的话&#xff0c;Eclipse则称得上是石器时代的东西了。其实笔者也是一枚从Eclipse转IDEA的探索者&#xff0c;随着近期的不断开发实践和调试&#xff0c;逐步体会到这款智能IDE带来的巨大开发便利&…

IDEA 使用入门

intellij 来阿里之前&#xff0c;还在使用eclipse&#xff0c;后来受无独 同学影响&#xff0c;开始使用intellij&#xff0c;从此以后再也没想过回到eclipse。最近周边的人使用intellij越来越多&#xff0c;还有一部分在eclipse和intellij之间徘徊选择&#xff0c;本文目的是…

idea新手使用教程总结

前言 本教程建立在建设你对idea有一个初步的概念,方便你更快的掌握和使用Intellij Idea开发工具。 由于本人使用的是Windows系统,故下方的所有演示均在Windows系统环境下 Windows下安装 系统环境要求 系统支持:Microsoft Windows 8 / 7 / Vista / 2003 / XP(每个系统版本…

IntelliJ IDEA 使用教程(2019图文版)

前言&#xff1a;IntelliJ IDEA 如果说IntelliJ IDEA是一款现代化智能开发工具的话&#xff0c;Eclipse则称得上是石器时代的东西了。其实笔者也是一枚从Eclipse转IDEA的探索者&#xff0c;随着近期的不断开发实践和调试&#xff0c;逐步体会到这款智能IDE带来的巨大开发便利…

IntelliJ IDEA使用教程创建Java 应用程序

前言 在本教程中&#xff0c;您将学习如何创建、运行和打包打印到系统输出的简单 Java 应用程序。在此过程中&#xff0c;您将熟悉IntelliJ IDEA功能&#xff0c;以提高开发人员的工作效率&#xff1a;编码辅助和补充工具。 IDE解释 IDE&#xff08;集成开发环境&#xff09;&a…

IDEA的使用教程

JDK、JRE、JVM JDK&#xff1a;Java Development Kit&#xff08;java开发者工具&#xff09;要开发java程序就需要有JDKJRE&#xff1a;Java Runtime Environment&#xff08;Java运行环境&#xff09;有JRE就可以运行Java程序JVM&#xff1a;Java Virtual Machine&#xff0…

IntelliJ IDEA 实用操作教程

作者&#xff1a;胡川港 知乎主页&#xff1a;zhihu.com/people/hu-chuan-gang-58 GitHub主页&#xff1a;https://github.com/xiaoxiunique 本文介绍了 IDEA 中令人相见恨晚的技巧&#xff0c;文中从入门、简单项目创建开始&#xff0c;介绍 IDEA 中多光标操作、常用配置、插件…

[IDE]IntelliJ IDEA使用教程(很全)

这个编辑器我就不再多做介绍了。直接开始新建maven hello world 的Java web项目啦 你电脑上得有jdk1.7&#xff0c;或者1.8&#xff0c;然后就是maven3.x吧&#xff0c;再有就是tomcat7以上吧。还得有我这个编辑器。这些是准备条件 下面就直接开始看图啦&#xff1a; 这个我刚…

IntelliJ IDEA的使用教程

1. 下载 地址: IntelliJ IDEA: The Capable & Ergonomic Java IDE by JetBrains 2. 个性化设置 2.1 intellij设置经典样式(背景为黑色的经典样式Darcula) 2.2 代码编辑字体修改 2.3 修改字符编码集 为了消除乱码问题与配置的简化&#xff0c;实际的项目中&#xf…

idea使用教程-idea简介

集成开发环境&#xff08;IDE&#xff0c;Integrated Development Environment &#xff09;是用于提供程序开发环境的应用程序&#xff0c;一般包括代码编辑器、编译器、调试器和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务…

Java基础语法(十九):IDEA使用教程

目录 一、下载IDEA 二、常用设置 三、常用快捷键 四、常用插件 五、中文汉化 一、下载IDEA 下载地址&#xff1a;IDEA官网 然后点击下载按钮。 然后自行选择所需要的版本。 Ultimate &#xff08;旗舰&#xff09;版本功能最全&#xff0c;但是只有30天的有效期&#x…

IDEA使用教程汇总

一、介绍 IDEA全称IntelliJ IDEA&#xff0c;是java语言开发的集成环境。idea提倡的是智能编码&#xff0c;目的是减少程序员的工作&#xff0c;其特色功能有智能的选取、丰富的导航模式、历史记录功能等&#xff0c;最突出的功能是调试&#xff08;Debug&#xff09;&#xf…

idea使用教程-安装

【1】将安装包进行解压--》选择固态盘符 【2】发送到桌面快捷方式&#xff0c;生成一个快捷方式 【3】打开&#xff1a; 选择主题&#xff1a; 先进入再说&#xff0c;免费试用&#xff1a; 创建一个项目&#xff1a; 选择JDK&#xff1a; 找到jetbrains-agent.jar 文件&#x…

idea使用教程,这一篇就足够了

写这篇文章的初衷&#xff0c;是由于自己最近入职了一个公司&#xff0c;需要配置环境&#xff0c;期间短短一周&#xff0c;换了三次设备&#xff0c;每次一边配置一边上网查的感觉很糟糕&#xff0c;所以我就打算写一个“一篇就足够”系列。主要是根据我自己的一些使用习惯来…

【IDEA】IntelliJ IDEA使用教程(2019图文版)

前言&#xff1a;IntelliJ IDEA 如果说IntelliJ IDEA是一款现代化智能开发工具的话&#xff0c;Eclipse则称得上是石器时代的东西了。其实笔者也是一枚从Eclipse转IDEA的探索者&#xff0c;随着近期的不断开发实践和调试&#xff0c;逐步体会到这款智能IDE带来的巨大开发便利…

IntelliJ IDEA 使用教程

一、设置入口 1、快捷键&#xff1a;Ctrl Alt S 2、File > Settings 3、View > appearance > Toolbar&#xff08;单击选中&#xff09; 出现工具栏图标&#xff0c;以后可直接点击它进入设置界面 之后的相关设置后&#xff0c;请点击Apply应用生效。 二、插件设…

IDEA的使用,手把手带你快速入门IDEA

目录 首次使用方法 创建java项目的方式 1.创建java项目 2.选择JDK和java项目 ​ 3.选择文件路径 ​ 新建包及类的方式 1.在src内右键选择Package 2.在包内右键选择java Class 运行java类的方式 创建模块 Eclipse 和 Idea 的对比 ​ IDEA的常用配置 设置鼠标滚轮…

Java开发工具 IntelliJ IDEA(idea使用教程,手把手教学)内容很全,一篇管够!!!

IDEA使用教程 下载安装 IntelliJ IDEA 介绍 IDEA&#xff0c;全称 IntelliJ IDEA&#xff0c;是 Java 语言的集成开发环境&#xff0c;IDEA 在业界被公认为是最好的 java 开发工具之一&#xff0c;尤其在智能代码助手、代码自动提示、重构、J2EE 支持、Ant、JUnit、CVS 整合…