第一讲里没有具体需要好好理解的部分,不过自测题目题目值得过一遍。
1.线性方程Ax=b的求解
有线性方程$Ax=b$,若已知$A,b$,需要求解$x$,该如何求解?这对$A$和$b$有哪些要求?
(提示:从$A$的维度和秩的角度来分析)
这个问题很简单,但是值得全面地分析和理解:
首先假设$A$是一个$m \times n$矩阵,$x$是一个$n \times 1$的列向量,$b$是一个$m \times 1$的列向量。这里的$m$表示方程的数量,$n$表示未知数的数量。
先从矩阵的秩出发来理解,以列的角度看,矩阵的秩表示了所有列向量线性组合所能达到的空间范围,对于方程$Ax=b$,如果向量$b$在矩阵$A$的列空间中($b$可以被$A$的列向量线性表示),那么存在至少一个解$x$使得$Ax=b$,因此就有了下面的判断性质(比较矩阵$A$和增广矩阵$A|b$秩的关系):
- $rank(A) = rank(A|b)$:表明向量$b$在矩阵$A$的列空间中,因此至少存在一个解$x$使得$Ax=b$。
- $rank(A) < rank(A|b)$:表明$b$不在$A$的列空间中,因此没有解。
然后再分析$rank(A)$来确定解的情况,是有唯一解还是存在多个解:
- 如果$rank(A)=n$(未知数的数量,也就是列的数量),则$A$的所有列向量都是线性独立的,意味着对于给定的$b$,存在唯一的$x$满足$Ax=b$。
- 如果$rank(A)<n$,则$A$中的某些列向量是其他列向量的线性组合,意味着给定的$b$时,这些可以被其他列向量表示的向量不参与线性组合出$b$,也就可以有任意值作为系数,导致存在无限多个解。
线性方程$Ax=b$的求解方法
‼️以下的回答来自GPT,自己还不是很理解,需要重新系统学习线性代数的知识后再进行自己的消化吸收!
- 超定系统:$m > n$,方程数量多于未知数。
- 欠定系统:$m < n$,方程数量少于未知数。
- 适定系统:$m = n$,方程数量等于未知数。
LU分解
- 原理:将矩阵$A$分解为两个特殊的矩阵乘积,一个下三角矩阵$L$和一个上三角矩阵$U$,即$A=LU$。这样,原始问题$Ax=b$变为求解两个更简单的线性方程组$L(Ux)=b$。
- 求解过程:首先解$L\mathbf{y}=b$找到$\mathbf{y}$,然后解$Ux=\mathbf{y}$找到$x$。
- 适用性:特别适用于适定系统,也可用于某些类型的超定和欠定系统,假设$A$可以进行有效的LU分解。
QR分解
- 原理:将矩阵$A$分解为一个正交矩阵$Q$和一个上三角矩阵$R$,即$A=QR$。正交矩阵具有性质$Q^TQ=I$($I$是单位矩阵)。
- 求解过程:利用$Q$的正交性质,原方程$Ax=b$变为$QRx=b$,进一步化简为$Rx=Q^Tb$,然后可以通过回代求解上三角方程组$Rx=Q^Tb$来找到$x$。
- 适用性:适用于所有类型的系统,尤其是超定系统,因为QR分解提供了一种求解最小二乘问题的自然方法。
奇异值分解(SVD)
- 原理:SVD将矩阵$A$分解为三个矩阵的乘积,即$A=U\Sigma V^T$,其中$U$和$V$是正交矩阵,$\Sigma$是对角矩阵,对角线上的元素是所谓的奇异值。
- 求解过程:对于方程$Ax=b$,可以转换为$\Sigma y=U^Tb$(这里$y=V^Tx$),然后通过求解$\Sigma y=U^Tb$来找到$y$,进一步求得$x=Vy$。
- 适用性:SVD是一种非常强大的方法,特别是对于奇异矩阵或矩阵秩不满的情况,因为它允许计算伪逆矩阵$A^+$,即使在$A$不可逆的情况下也能找到最小二乘解或最小范数解。
迭代方法求解
- 原理:迭代方法是从一个初始估计开始,通过重复应用迭代公式来逐步逼近方程的解。常见的迭代方法包括雅可比方法、高斯-赛德尔方法和共轭梯度法等。
- 求解过程:根据具体的迭代公式,每一步都基于前一步的结果来更新解的估计值,直至满足某个终止条件(如解的变化小于某个阈值)。
- 适用性:迭代方法特别适用于大规模稀疏矩阵的系统,因为它们通常不需要矩阵分解,而矩阵分解在大规模问题上可能非常昂贵。
2.高斯分布
高斯分布是什么?它的一维形式是什么样子?它的高维形式是什么样子?
高斯分布,也称为正态分布,高斯分布可以被视为描述自然和人为现象中随机误差的理想模型,其普遍性来源于中心极限定理(Central Limit Theorem, CLT),这个定理说明了许多小效应的累积可以产生高斯分布的现象,具体而言就是:“大量相互独立且分布相同的随机变量之和趋向于服从正态分布,无论原始随机变量的分布如何。”
高斯分布的一维形式
一维高斯分布(或简称为正态分布)的数学表达式为:
$$ f(x | \mu, \sigma^2) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp\left(-\frac{(x-\mu)^2}{2\sigma^2}\right) $$
其中,$\mu$是分布的均值,$\sigma^2$是方差,$\sigma$是标准差。这个公式描述了在给定均值$\mu$和方差$\sigma^2$的情况下,随机变量$X$取特定值$x$的概率密度。图形上,一维高斯分布是一个对称的钟形曲线,其中心位于均值$\mu$,曲线的宽度由标准差$\sigma$决定。
高斯分布的高维形式
高维高斯分布,或多变量高斯分布,是一维高斯分布在多维空间中的推广。其数学表达式为:
$$ f(\mathbf{x} | \boldsymbol{\mu}, \Sigma) = \frac{1}{\sqrt{(2\pi)^k |\Sigma|}} \exp\left(-\frac{1}{2}(\mathbf{x}-\boldsymbol{\mu})^T \Sigma^{-1} (\mathbf{x}-\boldsymbol{\mu})\right) $$
其中,$\mathbf{x}$是一个$k$维随机向量,$\boldsymbol{\mu}$是均值向量,$\Sigma$是协方差矩阵,$|\Sigma|$是协方差矩阵的行列式。高维高斯分布的图形是在多维空间中的一个“山峰”,其中心位于均值向量$\boldsymbol{\mu}$,“山峰”的形状和方向由协方差矩阵$\Sigma$决定。
协方差是衡量两个随机变量联合变化趋势的度量。如果两个变量的增减趋势相同(即一个变量增加时,另一个也增加),则它们的协方差为正;如果一个变量增加时另一个减少,则协方差为负。
对于两个随机变量$X$和$Y$,协方差定义为$Cov(X, Y) = E[(X - \mu_X)(Y - \mu_Y)]$,其中$\mu_X$和$\mu_Y$分别是$X$和$Y$的均值,$E$表示期望值操作。
3.C++基本知识
C++中的类是什么?STL是什么?模版又是什么?
(将基本常用的举例出来进行说明)
C++11的新特性以及其他标准
对于C和C++,我觉得需要系统的课程来学习补充,边用边学是持续的,先打好基础,边学边成长才更好
以下只是对这个回答的简要回答(举例说明)
类(Class)
类是C++中用于数据封装和面向对象编程的基本构建块。它定义了一种数据类型的蓝图,包括数据成员(属性)和成员函数(方法),用于操作这些数据。
class Car {
public:
Car(int y, const std::string& m) : year(y), model(m) {}
void display() const {
std::cout << "Year: " << year << ", Model: " << model << std::endl;
}
private:
int year;
std::string model;
};
标准模板库(STL)
STL是一组模板化的通用类和函数的集合,提供了常见的数据结构(如向量、列表、队列等)和算法(如排序、搜索等)。STL的核心组成部分包括:
- 容器:存储数据的数据结构。例如
std::vector
、std::list
、std::map
等。 - 算法:操作数据的函数,例如
std::sort
、std::find
。 - 迭代器:提供对容器中元素的访问方式。
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<int> vec = {4, 1, 3, 5, 2};
std::sort(vec.begin(), vec.end());
for(int i : vec) {
std::cout << i << " ";
}
}
模板(Template)
模板允许在不指定具体类型的情况下编写代码。它们使得可以创建泛型类和函数,使代码更加灵活和可重用。
template <typename T>
T add(T a, T b) {
return a + b;
}
// 使用模板函数
int result = add<int>(1, 2);
C++11/14/17的新特性举例
C++11
- 自动类型推断(
auto
):让编译器自动推断变量的类型。 - 基于范围的
for
循环:简化了集合的遍历。 - 智能指针:如
std::shared_ptr
和std::unique_ptr
,管理动态分配的内存。 - Lambda表达式:允许定义匿名函数。
C++14
- 泛型Lambda:Lambda表达式中使用自动类型推断。
- 返回类型推断:函数的返回类型可以被自动推断。
C++17
- 结构化绑定:允许从数组或元组中一次性解包多个值。
- 内联变量:对于头文件中的全局变量,允许多个源文件中包含同一个变量而不会引起重定义错误。
std::optional
:表示一个可能不存在的值。
4.Linux必备的操作
Linux必备知识
-
基本命令行操作: 理解如何使用命令行界面(CLI)进行文件系统的导航(如
cd
,ls
,pwd
)、文件操作(如cp
,mv
,rm
,mkdir
)和文本文件查看与编辑(如cat
,nano
,vi/vim
)。 -
软件安装与管理: 熟悉所用发行版的包管理器,如Ubuntu的
apt
, CentOS的yum
或Fedora的dnf
,用于安装、更新和管理软件包。 -
权限和用户管理: 了解文件权限(
chmod
,chown
)和用户管理命令(useradd
,usermod
,groupadd
),以及如何使用sudo
来执行需要超级用户权限的命令。 -
进程管理: 学会如何使用
ps
,top
,htop
,kill
, 和systemctl
来查看和管理运行中的进程和服务。 -
网络配置和故障排除: 掌握使用
ifconfig
/ipconfig
,ping
,netstat
,ss
,traceroute
等命令进行网络配置和故障排查。 -
Shell脚本编写: 学习基本的Shell脚本编写,以自动化日常任务。
-
文件系统管理: 了解不同的文件系统类型,磁盘分区(
fdisk
,parted
),以及如何挂载和卸载文件系统(mount
,umount
)。 -
安全和防火墙: 基本的系统安全知识,如使用
iptables
或ufw
管理防火墙规则,以及使用ssh
进行安全远程登录。
Linux的一些“术”
- 使用
man
命令: 几乎所有Linux命令都有手册页,通过man <命令名>
可以查看详细的使用说明和选项。 - 命令行自动完成: 通过按
Tab
键自动完成命令名称或参数,这不仅可以加快命令输入速度,还可以帮助记忆命令。 - 使用
apropos
命令: 如果不确定使用哪个命令,可以通过apropos <关键词>
来搜索相关的命令。 - 建立个人命令备忘录: 当学习新命令时,将它们记录在笔记中,随时查阅。
Linux安装软件
在使用apt
(或apt-get
)在Ubuntu或基于Debian的系统中安装软件时,软件包通常会被安装到系统的标准目录下,这遵循了Linux的文件系统层次结构标准(FHS)。大部分可执行文件会放置在/usr/bin/
或/usr/local/bin/
目录下,库文件通常位于/usr/lib/
或/usr/local/lib/
,而配置文件大多数在/etc/
下。文档和示例文件可能位于/usr/share/doc/
。
如何安装软件
如果你只是模糊知道某个软件包的名字,可以使用apt
提供的搜索功能来查找正确的软件包名。以下是步骤和示例,以Eigen这个数学库为例:
-
更新软件包列表:首先,最好更新本地软件包列表,以确保搜索和安装的是最新版本的软件。在终端中运行:
sudo apt update
-
搜索软件包:如果不确定软件包的确切名称,可以使用
apt-cache search
命令进行搜索。例如,如果要搜索Eigen,可以运行:apt-cache search eigen
这将列出所有与“eigen”相关的软件包。在结果中,会看到很多与Eigen相关的包,其中可能包括实际的Eigen库包和其他相关包。
-
安装软件包:一旦你找到了想要安装的确切软件包名称,就可以使用
apt-get install
命令进行安装。如果结果显示Eigen的开发包是libeigen3-dev
(这是一个常见的包名,用于包含Eigen库的开发文件),就可以运行:sudo apt-get install libeigen3-dev
这条命令会安装Eigen库及其所有依赖项。
如何找到安装的软件
如果想知道apt
安装的软件具体放在哪里,可以使用dpkg -L
命令来列出软件包安装的所有文件的位置。例如,要找到libeigen3-dev
安装的所有文件,可以运行:
dpkg -L libeigen3-dev
这将列出所有由该软件包安装的文件和目录的路径,包括库文件、头文件、文档等。
✨Linux的文件系统
Linux的文件系统层次结构标准(FHS, Filesystem Hierarchy Standard)定义了操作系统中目录和目录内容的标准布局。这种标准化设计使得开发者和用户能够预测在任何基于Linux的系统上找到特定类型文件的位置。以下是一些主要目录及其用途的简要说明:
根目录 /
在Linux中,所有的文件和目录都从根目录开始。这是整个文件系统的起点。
/bin
这个目录包含执行文件(二进制文件),这些文件是系统启动和运行所必需的,同时也存放了用户常用的命令(如ls
, cp
等)所依赖的执行文件。
用例:存放基本的命令,如grep
, echo
, sleep
。这些命令在单用户模式下或紧急恢复时也必须可用。
/boot
包含启动Linux系统所需的文件,比如Linux内核(vmlinuz
),引导加载程序(GRUB或LILO)的配置文件等。
/dev
这个目录下包含设备文件。Linux将设备视为文件,这些设备文件代表系统中的硬件组件。
/etc
包含系统配置文件。这些文件只能被根用户或具有适当权限的用户修改。这里包括系统启动脚本、网络配置文件等。
用例:包含如/etc/passwd
(用户账户信息)和/etc/fstab
(文件系统挂载的静态信息)等关键配置文件。
/home
用户的个人目录位于此处。每个用户都有一个与其用户名对应的目录,用于存储个人文件、配置等。
/lib
包含系统最基本的共享库和内核模块。这些库支持位于/bin
和/sbin
目录中的二进制文件。
用例:存放动态链接库(如libc.so.6
),它们是执行/bin
和/sbin
下命令所必需的。
/media
和/mnt
/media
通常用于挂载可移动媒体设备,如CD-ROMs、USB驱动器等,而/mnt
则用作临时挂载文件系统的目的。
/opt
用于安装“可选”的软件应用。这些是非基本系统软件,通常作为整个应用程序安装在这里。
用例:第三方应用程序如Google Chrome或某些商业软件可能会安装在这里,每个应用通常有其自己的子目录。
/proc
这是一个虚拟文件系统,提供对内核和进程信息的接口。它并不占用磁盘空间,而是在内存中动态生成。
/root
这是系统管理员,也就是root用户的家目录。这与/home
目录分开,为了安全性和管理方便。
/sbin
包含系统管理和维护的必需的执行文件,这些命令通常由root用户运行,如fdisk
, ifconfig
, swapon
等。
/tmp
一个临时文件存储区域。系统和用户可以在这里创建临时文件。通常,此目录在系统重启时会被清空。
/usr
包含用户程序和数据。它是Unix System Resources的缩写。随着时间的推移,/usr
目录已经成为存储共享系统资源的主要目录。
/usr/bin
:包含用户安装的非系统必需的执行文件。/usr/lib
:类似/lib
,但是为/usr/bin
下的程序提供库支持。/usr/local
:用于系统管理员安装本地软件,保持与由包管理器安装的软件的分离。- 用例:
/usr/bin
下可能会有如python
,gcc
等用户级程序。
/var
包含经常变化的文件,如日志文件、打印队列、邮件等。
/var/log
:存放系统日志文件,如/var/log/syslog
或/var/log/apache2
。/var/mail
:存储用户的邮件。/var/cache
:用于存放应用程序缓存数据。- 用例:系统管理员可能需要定期检查
/var/log
来监控系统和应用程序的活动。
/srv
用于存放服务提供的数据,例如Web服务器和FTP服务器的数据文件。
用例:如果您运行一个Web服务,网站的数据可能位于/srv/www
。
/sys
与/proc
相似,/sys
是一个虚拟文件系统,提供了内核、设备和驱动程序的接口。
用例:/sys
提供了一种更加结构化的方式来浏览设备和驱动程序的信息,如查询特定USB设备的信息。
/etc/cron.*
这些目录(cron.daily
, cron.hourly
, cron.monthly
, cron.weekly
)用于存放定时执行的脚本。
用例:自动备份脚本可能放在/etc/cron.daily
中,以确保每天执行。
5.Vim必须会的几个操作
已经不在执着于美化Vim的各种插件了(因为完全可以用更好的CLion、VSCode之类)
‼️但是命令行中Vim最方便,但只要知道最基础的操作就足够了:怎么增删改查,怎么复制粘贴。
Vim是一个非常强大的文本编辑器,常被用于编程和脚本编辑。它的操作方式与其他文本编辑器有很大不同,主要基于键盘快捷键,分为多种模式,最主要的是普通模式(Normal Mode)、插入模式(Insert Mode)、命令模式(Command-Line Mode)和可视模式(Visual Mode)。以下是关于Vim的基本用法,包括增删改查、复制粘贴,以及批量执行命令的方法。
Vim的基本操作
进入插入模式
- 在普通模式下,按
i
进入插入模式,在光标前插入文本。 - 按
a
也可以进入插入模式,在光标后插入文本。 - 按
I
在当前行首进入插入模式,按A
在当前行尾进入插入模式。
删除文本
- 在普通模式下,按
x
删除光标所在位置的字符。 - 按
dd
删除光标所在行。 - 要删除从当前光标位置到行尾的内容,可以使用
D
。
修改文本
- 在普通模式下,按
r
后跟一个字符可以替换光标所在位置的字符。 - 使用
cw
可以更改光标开始的单词,这将删除单词并进入插入模式。
查找文本
- 在普通模式下,按
/
后输入要查找的文字,然后按Enter
进行搜索。按n
查找下一个匹配项,按N
查找上一个匹配项。
复制和粘贴
- 在普通模式下,按
yy
复制当前行,按p
粘贴到光标后。 - 要复制多行,可以先按
2yy
来复制两行(2
可以替换为任何数字,表示行数)。 - 使用可视模式(按
v
进入)可以选择特定的文本区域,然后按y
复制。
移动操作
- 基本移动:
h
(左移)、j
(下移)、k
(上移)、l
(右移)。 - 按单词移动:
w
:向前移动到下一个单词的开头。b
:向后移动到前一个单词的开头。e
:向前移动到当前或下一个单词的结尾。
- 按行移动:
0
(零):移动到当前行的开始。^
:移动到当前行的第一个非空白字符。$
:移动到当前行的末尾。
- 跳转到特定行:
gg
:跳转到文件的第一行。G
:跳转到文件的最后一行。:<行号>
+Enter
:跳转到文件中的特定行号。
- 屏幕移动:
H
:移动到屏幕顶部的行。M
:移动到屏幕中间的行。L
:移动到屏幕底部的行。
- 翻页:
Ctrl
+f
:向前翻一页。Ctrl
+b
:向后翻一页。Ctrl
+d
:向前翻半页。Ctrl
+u
:向后翻半页。
可以结合前置数字来实现“批量移动”,这意味着可以在移动命令前加上一个数字来重复该命令多次,例如:
5j
表示向下(j
)移动5行。3w
表示向前跳过3个单词到下一个单词的开头。10k
表示向上(k
)移动10行。4$
表示移动到后面4行的末尾。
Vim与外部(macOS)的复制粘贴
在macOS上,从Vim复制文本到外部程序,首先需要确认你的Vim版本是否支持剪贴板(clipboard)功能。可以通过在终端中输入vim --version
查看。如果看到+clipboard
,则表示支持剪贴板功能;如果是-clipboard
,则表示不支持,可能需要安装支持剪贴板的Vim版本,比如通过brew install vim
。
-
启用剪贴板支持:确保Vim版本支持系统剪贴板。
-
复制文本到剪贴板:
- 在普通模式下,要复制整行到系统剪贴板,使用
"+yy
。(一个一个字符来按) - 要复制指定文本,先按
v
进入可视模式,选择需要的文本,然后使用"+y
复制。
- 在普通模式下,要复制整行到系统剪贴板,使用
-
从外部粘贴到Vim:在插入模式下,使用
Cmd
+V
(macOS通常的粘贴快捷键)或在普通模式下使用"+p
来粘贴剪贴板的内容到Vim。
一些技巧
-
在普通模式下,可以通过
:norm
命令批量执行操作。比如,:norm I//
会在所有选中的行前添加//
(注释掉这些行)。 -
批量替换文本,可以使用
:s
命令。例如,要在整个文件中替换"old"为"new",可以使用:s/old/new/g
。 -
在多个行前添加内容:假设想在文件的每一行前添加序号或特定标记,可以使用
:norm
命令。例如,:5,10norm I//
会在第5行到第10行的开头添加//
。 -
转换大小写:要将选定行的文本转换为大写,可以使用
:norm
结合gU
命令。例如,:5,10norm gU$
会将第5到第10行的内容转换为大写。 -
快速跳转至匹配的括号:在普通模式下,使用
%
可以跳转至匹配的括号,这在编辑代码时非常有用。 -
撤销和重做:使用
u
来撤销最近的一次更改,使用Ctrl+r
来重做被撤销的更改。 -
打开/关闭行号显示:快速切换行号显示,可以使用
:set nu!
和:set rnu!
来分别切换绝对行号和相对行号的显示状态。