【BIT矩阵分析】第4章 矩阵分解

文章汇总可见上面的专栏 或者 共享文档链接,可在下面的在线文档 或者 本文里评论指错,谢谢大家的共同努力:BIT研究生矩阵分析速成指南

文章有目录,标题里有⭐❗的重点看看,一定要懂哈!

本专栏内容基本涵盖考点,适用于 北京理工大学 研究生 矩阵分析课程,标⭐❗的看会基本能做计算题,足够及格,证明题主要分布在第3章和第5章。

这一章直接看后面的奇异值分解谱分解,必考!建议结合学堂在线视频和后面B站博主的视频学!

满秩分解

基本不考,可以不用看

答案结果不唯一

步骤

  1. 初等行变换,换成行最简(最好化成只有阶梯处是1,同列其他行为0)

  2. 找到线性无关列,在原始矩阵中取出这几列,为B

  3. 计算C

  4. A=BC

例题:

正交三角分解

基本不考,可以不用看

UR分解

UR分解答案唯一

A(m*r)=UC

U是次酉矩阵

R是r阶 对角线元素为正的三角矩阵

UR分解例题

 

LU分解

LU分解例题

⭐奇异值分解

奇异值

奇异值即AAH 非零 特征值 开根号

注意下:下一章讲的谱范数就是最大的奇异值

奇异值分解

定义

求解步骤:

  1. 计算AAH特征值,得到奇异值

  2. 计算AAH的标准正交特征向量,组成V

  3. 计算AHA的标准正交特征向量,组成UH (如果A里有i,不能用这种方式) / 反推UH(A里有i,必须用反推的方法)

  4. 切记!正交+单位化

奇异值分解例题

以下这些例题都是比较麻烦的办法,建议看【行数较多/含有i的奇异值分解例题】那部分,比较常用。


例题2 

⭐行数较多/含有i的奇异值分解例题

求出U或V其中一个,用A=UΔV反推另一个

大部分时候都是求得U,然后在A=UΔV等式左右都乘上U-1、Δ-1,然后就得到V了。

如果出现U的列数不够,列方程解出和前面已有列正交的向量作为缺少的列,如下。

切记H运算需要将复数正负符号取反(共轭)

注意:关键在求正交

(一些引理)

⭐谱分解【先判断是否正规矩阵:AAH=AHA

❗❗❗先判断是否正规矩阵:AAH=AHA

注意λ有0,0也要写到最后表达式

正规矩阵:

  1. 求λ及其特征向量

  2. 正交化单位化

  3. 写G

  4. 写表达式A=λG+....

其他矩阵:

  1. 求λ及其特征向量

  2. 特征向量组成P

  3. (P^-1)^T

  4. 写G

  5. 写表达式A=λG+....

正规矩阵 的 谱分解

即:AAH=AHA

需要单位化正交化

注意向量取的是H不是转置T,和下面的不同

可对角化矩阵/单纯矩阵 的 谱分解

除了正规矩阵以外的情况

不需要单位化

注意向量取的是转置T不是H,和上面的不同

步骤:

例题:

例题

❗复数域向量内积

如果上述正交化的变量有涉及到复数的,后面那个变量取共轭

可对角化

有n个两两互异特征值,或n个线性无关特征向量。

特征向量求法

步骤

  1. 找特征值

  2. 对每个特征值λ,代回λI-A

  3. 解方程(有几列就有几个未知数)

线性无关特征向量个数与秩的关系

对于n维矩阵A,其属于特征值λ的线性无关特征向量的个数为 n-r(A-λE) ,其中 r(A-λE) 表示矩阵 A-λE 的秩

普通特征向量个数和秩无关

❤️向量的内积 向量的模

感谢:

Bilibili(必看):翟男不宅的个人空间-翟男不宅个人主页-哔哩哔哩视频

Bilibili(校友总结):学疯蔚然的个人空间-学疯蔚然个人主页-哔哩哔哩视频

Bilibili(校友总结):这是谁啊好难猜的个人空间-这是谁啊好难猜个人主页-哔哩哔哩视频

Github(必看):GitHub - DarkIceField/BIT_Matrix_Analysis

Bilibili:翰林苑长的个人空间-翰林苑长个人主页-哔哩哔哩视频

Bilibili:热爱读研的铛铛的个人空间-热爱读研的铛铛个人主页-哔哩哔哩视频

如有侵权,请联系删除

<think>好的,我现在需要帮用户解决使用Keil开发51单片机实现4x4矩阵键盘和数码管的简易计算器的问题。用户之前提供的引用内容提到了硬件组成和部分代码,比如矩阵键盘扫描和数码管驱动。但用户现在需要的是具体的示例代码,所以我要综合这些信息来构建一个合适的程序框架。 首先,得确定硬件连接。根据引用1和2,主控是STC89C52,4x4矩阵键盘连接到P3口,数码管使用8位共阳,通过74HC573锁存器驱动。可能需要用到P0和P2控制段选和位选。需要确认键盘扫描部分的引脚分配,比如引用3中的代码里,矩阵键盘的列扫描是通过P3口,行输入也是P3的低四位。所以键盘扫描函数可能需要类似的处理。 接下来,程序的结构大致分为几个部分:键盘扫描、数码管显示、计算逻辑处理。键盘扫描需要检测按键,并将按键值转换为对应的数字或操作符。数码管显示需要动态扫描,每个时刻点亮一位,保持视觉暂留。计算逻辑需要处理输入的数字、运算符,并执行运算,处理正负号,错误提示等。 考虑到用户需求中的支持3位数输入、正负运算、最大显示999999,可能需要在代码中定义变量来存储输入的数、当前操作符、结果等。比如用两个操作数和一个操作符,当按下等号时计算结果。同时,错误处理比如除零错误需要检测,并显示提示。 键盘扫描部分可以参考引用3中的代码,使用行列扫描法,检测按键按下后去抖动,然后确定按键值。需要注意的是,按键编号到实际功能的映射,比如数字0-9,加减乘除,等于,清除等。例如,按键0-9对应数字,第10-13键为加减乘除,14为等于,15为清除。 数码管显示部分需要处理动态扫描,使用段码和位码。共阳数码管的段码需要根据硬件连接确定,比如0-F对应的段码值。可能需要查表法来转换数字到段码。同时,显示的内容需要根据当前输入状态更新,比如输入数字时显示当前数值,运算后显示结果,错误时显示特定符号。 主程序的结构可能是一个循环,不断扫描键盘,处理输入,更新显示。中断或者定时器可以用来定时刷新数码管,避免阻塞主循环。但根据引用3中的建议,使用定时器中断来处理数码管动态显示会更高效,避免CPU被时间占用。 此外,计算逻辑需要考虑连续输入的数字,比如输入123需要将每一位合并成整数。可能需要一个缓冲区存储当前输入的数字,当按下运算符时,将缓冲区转为操作数,并重置缓冲区。运算时需要考虑运算符优先级,但简易计算器可能按照顺序处理,不处理优先级,或者用户分步输入。 错误处理方面,比如除以零的情况,需要检测并在数码管显示错误信息,比如“E”或特定段码。同时,输入超过三位数时需要限制,或者在运算结果超过显示范围时提示错误。 现在需要考虑代码的具体实现。首先定义数码管的段码和位码,可能使用两个锁存器分别控制段选和位选。P0口连接段选,P2口控制位选。比如,使用74HC573锁存器,当需要改变段码时,先输出到P0,然后锁存;位选同理。 键盘扫描函数需要返回按下的键值,然后根据键值执行相应操作。比如,数字键则更新当前输入数值,运算符键则存储当前操作符并切换输入状态,等于键则计算结果。清除键则重置所有变量。 显示函数需要将当前数值转换为数码管的段码,并分时显示每一位。例如,将数值分解为各个位数,查表得到段码,依次点亮每一位数码管,保持一定时间间隔,利用视觉暂留效果。 在Keil中编程时,需要注意51单片机的寄存器配置,比如IO口模式,是否需要上拉电阻等。根据引用3中的代码,P3口用于矩阵键盘,需要设置为准双向口模式。 可能遇到的问题包括按键抖动处理、数码管显示亮度不均、运算逻辑错误等。需要确保键盘扫描有去抖动延时,如引用3中的Delay10ms函数。数码管动态扫描的频率要足够高,通常每位数码管点亮1-2ms,整体刷新率在50Hz以上以避免闪烁。 最后,整合这些部分,编写示例代码,包括头文件、引脚定义、全局变量声明、函数原型、键盘扫描、数码管显示、主循环和中断服务函数等。需要测试代码的逻辑是否正确,比如按键输入、运算处理、显示更新等步骤是否协调工作。</think>以下是为您整理的51单片机简易计算器示例代码框架,包含矩阵键盘扫描和数码管显示功能: ```c #include <reg52.h> #include <intrins.h> // 硬件定义 #define SEG_PORT P0 // 数码管段选 #define BIT_PORT P2 // 数码管位选 #define KEY_PORT P3 // 矩阵键盘接口 // 共阳数码管段码表(0-9) unsigned char code seg_table[] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, // 0-4 0x92, 0x82, 0xF8, 0x80, 0x90, // 5-9 0xBF, 0x7F, 0xFF // '-', ., 全灭 }; // 全局变量 long num1 = 0, num2 = 0, result = 0; char op = 0; // 运算符 bit input_flag = 0; // 输入状态 // 函数声明 void Delay1ms(unsigned int count); unsigned char KeyScan(); void Display(long num); void Calculate(); void main() { unsigned char key; while(1) { key = KeyScan(); if(key != 0xFF) { if(key <= 9) { // 数字输入 if(!input_flag) { num1 = num1 * 10 + key; if(num1 > 999) num1 = 999; } else { num2 = num2 * 10 + key; if(num2 > 999) num2 = 999; } } else if(key >= 10 && key <= 13) { // 运算符 op = key; input_flag = 1; } else if(key == 14) { // 等于 Calculate(); input_flag = 0; } else if(key == 15) { // 清除 num1 = num2 = result = 0; op = 0; input_flag = 0; } } Display(result ? result : (input_flag ? num2 : num1)); } } // 键盘扫描函数(改进版本) unsigned char KeyScan() { static unsigned char col = 0x01; unsigned char row, key = 0xFF; KEY_PORT = ~col; // 列扫描 if(KEY_PORT != ~col) { Delay1ms(10); // 去抖动 if(KEY_PORT != ~col) { row = (~KEY_PORT) & 0x0F; switch(row) { case 0x01: key = 0 + (col-1)*4; break; case 0x02: key = 1 + (col-1)*4; break; case 0x04: key = 2 + (col-1)*4; break; case 0x08: key = 3 + (col-1)*4; break; } while(KEY_PORT != ~col); // 等待按键释放 } } col <<= 1; if(col > 0x08) col = 0x01; return key; } // 显示函数(带符号处理) void Display(long num) { unsigned char i, digit; signed char negative = 0; unsigned char buf[8]; if(num < 0) { negative = 1; num = -num; } for(i=0; i<8; i++) { buf[i] = num % 10; num /= 10; } for(i=7; i>=0; i--) { SEG_PORT = seg_table[buf[i]]; if(i == 0 && negative) SEG_PORT &= 0x7F; // 显示负号 BIT_PORT = (0x01 << i); Delay1ms(2); BIT_PORT = 0xFF; } } // 计算函数 void Calculate() { switch(op) { case 10: result = num1 + num2; break; case 11: result = num1 - num2; break; case 12: result = num1 * num2; break; case 13: if(num2 == 0) result = 999999; // 错误标志 else result = num1 / num2; break; } // 结果范围检查 if(result > 999999 || result < -99999) result = 999999; num1 = result; num2 = 0; } // 延时函数 void Delay1ms(unsigned int count) { unsigned int i,j; for(i=0; i<count; i++) for(j=0; j<120; j++); } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值