【SLAM】最最最简单的直线拟合情形下的多种求解方法

本文我们讨论一个最最最简单情况下的拟合的情形,并尝试使用不同的方法来进行求解。

假如有一组数 x 1 , x 2 , x 3 , . . . , x n x_1,x_2,x_3,...,x_n x1,x2,x3,...,xn,对应的值为 y 1 , y 2 , y 3 , . . . , y n y_1,y_2,y_3,...,y_n y1,y2,y3,...,yn,并且 y y y x x x之间近似满足 y = k x + b y=kx+b y=kx+b的关系。求解出最佳的k的值。

为了方便后续的代码编写,这边就将 x i x_i xi y i y_i yi都定义下:

std::vector<Eigen::Vector2d> data = {{2.5, 2.4}, {0.5, 0.7}, {2.2, 2.9}, {1.9, 2.2}, {3.1, 3.0}, {2.3, 2.7}, {2, 1.6}, {1, 1.1}, {1.5, 1.6}, {1.1, 0.9}
};

最小二乘法

微分法

按照最小二乘法的定义:

假设 y ^ \hat{y} y^为满足近似关系的 y y y的值,即 y ^ i = k x i + b \hat{y}_i=kx_i+b y^i=kxi+b,那么也就是求解误差平方和

S S E = ∑ i = 1 n ( y i − y ^ i ) 2 = ∑ i = 1 n [ y i − ( k x i + b ) ] 2 SSE=\sum_{i=1}^{n}(y_i-\hat{y}_i)^{2}=\sum_{i=1}^{n}[y_i-(kx_i+b)]^{2} SSE=i=1n(yiy^i)2=i=1n[yi(kxi+b)]2

最小时的 k k k值。

这里,我们将误差视为关于 k k k b b b的函数,那么问题就变成了求各自偏导的问题了:

∂ S S E ∂ k = ∑ i = 1 n ( 2 k x i 2 − 2 x i y i + 2 b x i ) \frac{\partial SSE}{\partial k}=\sum_{i=1}^{n}(2kx_i^2-2x_iy_i+2bx_i) kSSE=i=1n(2kxi22xiyi+2bxi)

∂ S S E ∂ b = ∑ i = 1 n ( 2 b − 2 y i + 2 k x i ) \frac{\partial SSE}{\partial b}=\sum_{i=1}^{n}(2b-2y_i+2kx_i) bSSE=i=1n(2b2yi+2kxi)

令各自偏导数等于0,求解出:

k = n ∑ i = 1 n ( x i y i ) − ∑ i = 1 n ( x i ) ∑ i = 1 n ( y i ) n ∑ i = 1 n ( x i ) 2 − ( ∑ i = 1 n ( x i ) ) 2 k=\frac{n\sum_{i=1}^{n}(x_iy_i)-\sum_{i=1}^{n}(x_i)\sum_{i=1}^{n}(y_i)}{n\sum_{i=1}^{n}(x_i)^2-(\sum_{i=1}^{n}(x_i))^2} k=ni=1n(xi)2(i=1n(xi))2ni=1n(xiyi)i=1n(xi)i=1n(yi)

b = ∑ i = 1 n y i − k ∑ i = 1 n x i n b=\frac{\sum_{i=1}^{n}y_i-k\sum_{i=1}^{n}x_i}{n} b=ni=1nyiki=1nxi

下面的代码就使用该公式直接求解:

#include <iostream>
#include <vector>
#include <numeric>int main() {// 创建一个二维数据集std::vector<Eigen::Vector2d> data = {{2.5, 2.4}, {0.5, 0.7}, {2.2, 2.9}, {1.9, 2.2}, {3.1, 3.0}, {2.3, 2.7}, {2, 1.6}, {1, 1.1}, {1.5, 1.6}, {1.1, 0.9}};double x_sum = 0.0;double y_sum = 0.0;double xy_sum = 0.0;double x2_sum = 0.0;for (const auto& point : data) {x_sum += point[0];y_sum += point[1];xy_sum += point[0] * point[1];x2_sum += point[0] * point[0];}double n = static_cast<double>(data.size());// 使用微分法求解double slope = (n * xy_sum - x_sum * y_sum) / (n * x2_sum - x_sum * x_sum);double intercept = (y_sum - slope * x_sum) / n;// 输出结果std::cout << "Slope: " << slope << std::endl;std::cout << "Intercept: " << intercept << std::endl;return 0;
}

计算出的结果为:

y = 0.998198 x + 0.103262

矩阵法

按照最小二乘法的定义:

假设 y ^ \hat{y} y^为满足近似关系的 y y y的值,即 y ^ i = k x i + b \hat{y}_i=kx_i+b y^i=kxi+b,那么也就是求解误差平方和:

S S E = ∑ i = 1 n ( y i − y ^ i ) 2 = ( y − y ^ ) T ( y − y ^ ) SSE=\sum_{i=1}^{n}(y_i-\hat{y}_i)^{2}=(\mathbf{y}-\hat{\mathbf{y}})^T(\mathbf{y}-\hat{\mathbf{y}}) SSE=i=1n(yiy^i)2=(yy^)T(yy^)

其中,

y = [ y 1 y 2 . . . y n ] \mathbf{y}=\begin{bmatrix}y_1 \\ y_2 \\ ... \\ y_n\end{bmatrix} y= y1y2...yn

由于 y ^ i = k x i + b \hat{y}_i=kx_i+b y^i=kxi+b,那么:

y ^ = X θ \hat{\mathbf{y}}=\mathbf{X}\mathbf{\theta} y^=Xθ

其中,

X = [ x 1 1 x 2 1 . . . . . . x n 1 ] \mathbf{X}=\begin{bmatrix}x_1 & 1\\ x_2 &1 \\ ... & ... \\ x_n & 1\end{bmatrix} X= x1x2...xn11...1

θ = [ k b ] \mathbf{\theta}=\begin{bmatrix}k & b\end{bmatrix} θ=[kb]

那么,该问题就转化为求解 y ^ = X θ \hat{\mathbf{y}}=\mathbf{X}\mathbf{\theta} y^=Xθ的最小二乘解。

接下来,可以使用特征值方法、奇异值方法来进行求解。这部分的详细求解方法,可以参考文档:【Math】线性方程组的最小二乘解。

下面的代码就使用Eigen库的方法直接求解:

#include <Eigen/Dense>
#include <iostream>
#include <vector>int main() {// 创建一个二维数据集std::vector<Eigen::Vector2d> data = {{2.5, 2.4}, {0.5, 0.7}, {2.2, 2.9}, {1.9, 2.2}, {3.1, 3.0}, {2.3, 2.7}, {2, 1.6}, {1, 1.1}, {1.5, 1.6}, {1.1, 0.9}};// 创建设计矩阵A和目标向量bEigen::MatrixXd A(data.size(), 2);Eigen::VectorXd b(data.size());for (size_t i = 0; i < data.size(); ++i) {A(i, 0) = data[i](0);A(i, 1) = 1;b(i) = data[i](1);}// 使用最小二乘法求解Eigen::VectorXd x = A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);// 输出结果std::cout << "Slope: " << x(0) << std::endl;std::cout << "Intercept: " << x(1) << std::endl;return 0;
}

计算出的结果为:

y = 0.998198 x + 0.103262

迭代优化法

无论是微分法的:

S S E = ∑ i = 1 n ( y i − y ^ i ) 2 = ∑ i = 1 n [ y i − ( k x i + b ) ] 2 SSE=\sum_{i=1}^{n}(y_i-\hat{y}_i)^{2}=\sum_{i=1}^{n}[y_i-(kx_i+b)]^{2} SSE=i=1n(yiy^i)2=i=1n[yi(kxi+b)]2

还是,矩阵法的:

S S E = ∑ i = 1 n ( y i − y ^ i ) 2 = ( y − y ^ ) T ( y − y ^ ) SSE=\sum_{i=1}^{n}(y_i-\hat{y}_i)^{2}=(\mathbf{y}-\hat{\mathbf{y}})^T(\mathbf{y}-\hat{\mathbf{y}}) SSE=i=1n(yiy^i)2=(yy^)T(yy^)

都是求解一个最小二乘问题,上面采用的就是解析法求解的。对于这种类型的问题,同样也都可以使用迭代法进行迭代求解

对于迭代计算的优化方法,这里就不细讲了。之后会单开一章进行讲解,也可以参考文章:最小二乘问题的四种解法——牛顿法,梯度下降法,高斯牛顿法和列文伯格-马夸特法的区别和联系。


协方差法

假设有一组样本 x 1 , x 2 , x 3 , . . . , x n x_1,x_2,x_3,...,x_n x1,x2,x3,...,xn,这组样本的均值为 E ( X ) E(X) E(X),每一个样本都与 E ( X ) E(X) E(X)之间存在误差,那么这组样本的方差被定义为:所有误差的和的均值,也即 D ( X ) = E [ ( X − E ( X ) ) 2 ] D(X)=E[(X-E(X))^2] D(X)=E[(XE(X))2],方差的作用就是用来衡量样本偏离均值的程度

而协方差:

C O V ( X , Y ) = E [ ( X − E ( X ) ) ( Y − E ( Y ) ) ] = E ( X Y ) − E ( X ) E ( Y ) \begin{aligned}COV(X,Y)&=E[(X-E(X))(Y-E(Y))]\\&=E(XY)-E(X)E(Y)\end{aligned} COV(X,Y)=E[(XE(X))(YE(Y))]=E(XY)E(X)E(Y)

仔细观察上述定义式,可知:如果两个变量的变化趋势一致,也就是说如果其中一个大于自身的期望值时另外一个也大于自身的期望值,那么两个变量之间的协方差就是正值;如果两个变量的变化趋势相反,即其中一个变量大于自身的期望值时另外一个却小于自身的期望值,那么两个变量之间的协方差就是负值

也就是说,协方差是用来衡量两个变量之间协同变化趋势的总体参数,即二个变量相互影响的参数。不太清楚的可以参考文章:深入理解协方差(图文详解)。

判断线性相关的相关系数,定义为:

ρ = C O V ( X , Y ) D ( X ) D ( Y ) \rho=\frac{COV(X,Y)}{\sqrt{D(X)}\sqrt{D(Y)}} ρ=D(X) D(Y) COV(X,Y)

通过协方差的性质,如果满足 Y = k X + b Y=kX+b Y=kX+b,那么有:

C O V ( X , Y ) = C O V ( X , k X + b ) = C O V ( X , k X ) = k C O V ( X , X ) = k D ( X ) \begin{aligned}COV(X,Y)&=COV(X,kX+b)\\&=COV(X,kX)\\&=kCOV(X,X)\\&=kD(X)\end{aligned} COV(X,Y)=COV(X,kX+b)=COV(X,kX)=kCOV(X,X)=kD(X)

即:

k = C O V ( X , Y ) D ( X ) k=\frac{COV(X,Y)}{D(X)} k=D(X)COV(X,Y)

其实,这个公式和微分法计算出的 k k k是一致的:

k = n ∑ i = 1 n ( x i y i ) − ∑ i = 1 n ( x i ) ∑ i = 1 n ( y i ) n ∑ i = 1 n ( x i ) 2 − ( ∑ i = 1 n ( x i ) ) 2 k=\frac{n\sum_{i=1}^{n}(x_iy_i)-\sum_{i=1}^{n}(x_i)\sum_{i=1}^{n}(y_i)}{n\sum_{i=1}^{n}(x_i)^2-(\sum_{i=1}^{n}(x_i))^2} k=ni=1n(xi)2(i=1n(xi))2ni=1n(xiyi)i=1n(xi)i=1n(yi)


PCA法

主成分分析PCA是一种数学降维方法:利用正交变换把一系列可能线性相关的变量转换为一组线性不相关的新变量,也称为主成分,从而利用新变量在更小的维度下展示数据的特征。

主成分是原有变量的线性组合,其数目不多于原始变量。组合之后,相当于我们获得了一批新的观测数据,这些数据的含义不同于原有数据,但包含了之前数据的大部分特征,并且有着较低的维度,便于进一步的分析。

在空间上,PCA可以理解为把原始数据投射到一个新的坐标系统,第一主成分为第一坐标轴,它的含义代表了原始数据中多个变量经过某种变换得到的新变量的变化区间;第二成分为第二坐标轴,代表了原始数据中多个变量经过某种变换得到的第二个新变量的变化区间。这样我们把利用原始数据解释样品的差异转变为利用新变量解释样品的差异。

对于数据拟合的问题,我们可以看到,无论是正相关还是负相关,只要呈现为线性关系,那么它的主成分,相较于剩下的成分,一定是呈现出一个较大的差距。

在这里插入图片描述

那么,我们就可以通过这个来进行判断。

PCA的推导过程可以参考文章:一文让你彻底搞懂主成成分分析PCA的原理及代码实现(超详细推导)。

这里只介绍下最终计算方式:

假设有 n n n m m m维数据, X m × n = x 1 , x 2 , . . . , x n X_{m\times n}=x_1, x_2, ..., x_n Xm×n=x1,x2,...,xn,其中的每个 x i x_i xi是一个 m m m维的列向量,

  1. 去中心化, X = X − 1 n ∑ i = 1 n ( x i ) X=X-\frac{1}{n}\sum_{i=1}^{n}(x_i) X=Xn1i=1n(xi)
  2. 计算协方差矩阵, C O V = 1 n X X T COV=\frac{1}{n}XX^T COV=n1XXT
  3. 对协方差矩阵进行特征值分解得到 m m m个特征矩阵(按特征值从大到小以列排)

其中,这些特征值对应的特征向量就是这组数据的主成分

当然,除了对协方差矩阵进行特征值分解,SVD分解也是一种方式。

下面的代码就使用Eigen库的方法直接求解:

#include <Eigen/Dense>
#include <iostream>
#include <vector>int main() {// 创建一个二维数据集std::vector<Eigen::Vector2d> data = {{2.5, 2.4}, {0.5, 0.7}, {2.2, 2.9}, {1.9, 2.2}, {3.1, 3.0}, {2.3, 2.7}, {2, 1.6}, {1, 1.1}, {1.5, 1.6}, {1.1, 0.9}};// 计算数据的均值Eigen::Vector2d mean = Eigen::Vector2d::Zero();for (const auto& point : data) {mean += point;}mean /= static_cast<double>(data.size());// 将数据中心化Eigen::MatrixXd centeredData(data.size(), 2);for (size_t i = 0; i < data.size(); ++i) {centeredData.row(i) = data[i] - mean;}// 计算协方差矩阵Eigen::MatrixXd covariance = centeredData.transpose() * centeredData;// -----------------方法一:使用特征值// 计算协方差矩阵的特征值和特征向量Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> solver(covariance);Eigen::VectorXd eigenvalues = solver.eigenvalues();Eigen::MatrixXd eigenvectors = solver.eigenvectors();// 找到最大特征值对应的特征向量int maxEigenvalueIndex;eigenvalues.maxCoeff(&maxEigenvalueIndex);Eigen::Vector2d principalComponent = eigenvectors.col(maxEigenvalueIndex);// -----------------方法二:使用奇异值// 使用SVD找到数据的主成分Eigen::JacobiSVD<Eigen::MatrixXd> svd(centeredData, Eigen::ComputeThinU | Eigen::ComputeThinV);Eigen::Vector2d principalComponent = svd.matrixV().col(0);// 计算直线的斜率和截距double slope = principalComponent[1] / principalComponent[0];double intercept = mean[1] - slope * mean[0];std::cout << "Slope: " << slope << std::endl;std::cout << "Intercept: " << intercept << std::endl;return 0;
}

计算出的结果为:

y = 1.08454 x - 0.0530116

可以看出,这种方法计算出来的拟合值和上文的其他方法不太一样。但是也算是比较接近了。如果从SSE的角度衡量的话,自然是不如上面的方法精确的。


Ransac法

上面的所有方法,都有一个共性的缺点:不能避免异常离群点对最终拟合结果的影响。而RANSAC方法,就可以比较好的解决这个问题

RANSAC实际上是一种框架,而不是一个具体的拟合的算法。所谓具体的拟合方法,就是比如上面提到的这些算法。

RANSAC(Random Sample Consensus,随机采样一致)算法是从一组含有外点(outliers)的数据中正确估计数学模型参数的迭代算法。外点一般指的的数据中的噪声,尤其是一些离群点。所以,RANSAC也是一种外点检测算法

内点就是组成模型参数的数据,外点就是不适合模型的数据。同时RANSAC假设:在给定一组含有少部分内点的数据,存在一个程序可以估计出符合内点的模型。在本文中,这个程序,就是具体的拟合的算法。

RANSAC是通过反复选择数据集去估计出模型,一直迭代到估计出认为比较好的模型。 具体的实现步骤可以分为以下几步:

  1. 选择出可以估计出模型的较小的数据集(对于直线拟合来说就是较少点,甚至可以是两个点);
  2. 使用这个数据集来计算出数据模型(对较少点利用具体的拟合算法,来拟合出一条直线);
  3. 将所有数据带入这个模型,计算出内点的数目(累加在一定误差范围内的适合当前迭代推出模型的数据);
  4. 比较当前模型和之前推出的最好的模型的内点的数量,记录最大内点数的模型参数和内点数;
  5. 重复1-4步,直到迭代结束或者当前模型已经足够好了(内点数目大于一定数量)。

更细节的内容可以参考文章:RANSAC算法(附RANSAC直线拟合C++与Python版本)。

下面的代码就使用Eigen库的方法直接求解:

#include <Eigen/Dense>
#include <vector>
#include <random>
#include <limits>
#include <algorithm>// RANSAC直线拟合
Eigen::Vector2d ransacLineFitting(const std::vector<Eigen::Vector2d>& data,int maxIterations,double distanceThreshold,int numPoints) {std::random_device rd;std::mt19937 gen(rd());std::uniform_int_distribution<> dis(0, data.size() - 1);int bestInliers = 0;Eigen::Vector2d bestLine;for (int i = 0; i < maxIterations; ++i) {// 随机选择numPoints个点std::vector<Eigen::Vector2d> points;for (int j = 0; j < numPoints; ++j) {points.push_back(data[dis(gen)]);}// 计算直线参数// 利用上文的具体的拟合算法对points进行拟合,甚至可以numPoints取2,直接算斜率// 拟合结果:y = kx + b// 计算内点数int inliers = 0;for (const auto& point : data) {double distance = (point[1] - k * point[0] - b) * (point[1] - k * point[0] - b);if (distance < distanceThreshold) {++inliers;}}// 更新最佳模型if (inliers > bestInliers) {bestInliers = inliers;Eigen::Vector2d line(k, b);bestLine = line;}}return bestLine;
}int main() {// 创建一个二维数据集std::vector<Eigen::Vector2d> data = {{2.5, 2.4}, {0.5, 0.7}, {2.2, 2.9}, {1.9, 2.2}, {3.1, 3.0}, {2.3, 2.7}, {2, 1.6}, {1, 1.1}, {1.5, 1.6}, {1.1, 0.9}};// 使用RANSAC进行直线拟合Eigen::Vector2d line = ransacLineFitting(data, 1000, 0.1, 2);std::cout << "Line parameters: " << line[0] << ", " << line[1] << std::endl;return 0;
}

需要注意的是:对于RANSAC方法,numPoints的取值,不能太小,也不能太大。太小的话,可能导致拟合结果无法代表较多点数的方向;太大的话,可能无法规避掉外点造成的影响。需要权衡。


上面的几种方法都可以进行直线拟合,至于选择哪一种,取决于具体的情形和问题。

一般来说,最小二乘法是最常见、使用最广泛的方法,也是最需要掌握的。如果你是SLAM相关的从业人员,那么矩阵法、迭代优化法、Ransac法也是必须掌握的能力。


相关阅读

  • 最优化方法——最小二乘法与梯度下降法
  • 线性拟合1-最小二乘
  • 深入理解协方差(图文详解)
  • 超全面的协方差矩阵介绍
  • 一文让你彻底搞懂主成成分分析PCA的原理及代码实现(超详细推导)
  • RANSAC算法(附RANSAC直线拟合C++与Python版本)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/47707.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

10.11和10.8那个大(各种ai的回答)

问题&#xff1a;10.11和10.8两个数哪个大 腾讯混元 ✔️ chatGPT ❎ 通义千问 ❎ 文心一言 ✔️ 智谱清言 ❎ 讯飞星火 ✔️ C知道 ❎ 豆包 ✔️

TCP粘包问题详解和解决方案【C语言】

1.什么是TCP粘包 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输协议&#xff0c;它保证了数据的可靠性和顺序性。然而&#xff0c;由于TCP是基于字节流而不是消息的&#xff0c;因此在传输过…

【接口自动化_08课_Pytest+Yaml+Allure框架】

上节课一些内容 的补充 1、openxl这个方法&#xff0c;第一个元素是从1开始的&#xff0c;不是从0开始 回写的列在程序里写的是11&#xff0c;是因为是固定值 一、1. Yaml入门及应用 1、什么是yaml YAML&#xff08;/ˈjməl/&#xff0c;尾音类似camel骆驼&#xff09;是一…

Finding columns with a useful data type 找到合适的数据列的类型

Finding columns with a useful data type 在确定了原始查询的数据列数之后&#xff0c;接下来就是要确定合适的数据列的数据类型。可以用 SELECT a 的方式判断对应的数据列方式&#xff0c;有时候可以通过错误信息判断数据列的类型。如果服务器的响应没有报错&#xff0c;而…

一文带你了解提升私域成交的四大关键因素

对于消费者而言&#xff0c;在购物时&#xff0c;需求、触点和信任是三个必须满足的条件。这三者缺一不可&#xff0c;是构成购买决策的三大支柱。然而&#xff0c;在实际的购买流程中&#xff0c;这三个要素的出现顺序却可以有多种不同的组合方式。这些不同的顺序反映了消费者…

Docker启动PostgreSql并设置时间与主机同步

在 Docker 中启动 PostgreSql 时&#xff0c;需要配置容器的时间与主机同步。可以通过在 Dockerfile 或者 Docker Compose 文件中设置容器的时区&#xff0c;或者使用宿主机的时间来同步容器的时间。这样可以确保容器中的 PostgreSql 与主机的时间保持一致&#xff0c;避免在使…

启动流程和切换流程

启动流程 #mermaid-svg-iUWGw8xl1SyAmoo9 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-iUWGw8xl1SyAmoo9 .error-icon{fill:#552222;}#mermaid-svg-iUWGw8xl1SyAmoo9 .error-text{fill:#552222;stroke:#552222;}#…

C语言·分支和循环语句(超详细系列·全面总结)

前言&#xff1a;Hello大家好&#x1f618;&#xff0c;我是心跳sy&#xff0c;为了更好地形成一个学习c语言的体系&#xff0c;最近将会更新关于c语言语法基础的知识&#xff0c;今天更新一下分支循环语句的知识点&#xff0c;我们一起来看看吧~ 目录 一、什么是语句&#xf…

C++ 的 SFINAE(Substitution Failure Is Not An Error) 机制和类型萃取(type traits)

C 的 SFINAE&#xff08;Substitution Failure Is Not An Error&#xff09; 机制和类型萃取&#xff08;type traits&#xff09; flyfish Substitution Failure Is Not An Error 翻译为中文是“替换失败不是错误”。它是 C 模板编程中的一个重要概念&#xff0c;指在模板实…

Bootstrap 导航栏:设计、定制与实现

Bootstrap 导航栏&#xff1a;设计、定制与实现 Bootstrap 是一个流行的前端框架&#xff0c;它提供了丰富的组件和工具&#xff0c;帮助开发者快速构建响应式和移动优先的网页。在 Bootstrap 的众多组件中&#xff0c;导航栏&#xff08;Navbar&#xff09;是一个核心元素&am…

linux配置podman阿里云容器镜像加速器

1.下载podman yum install -y podman systemctl status podman systemctl start podman 2.获取阿里云个人容器镜像加速器地址 访问阿里云官网&#xff1a;首先&#xff0c;您需要访问阿里云&#xff08;Alibaba Cloud&#xff09;的官方网站。阿里云官网的URL是&#xff1a;…

使用 Arthas 进行 Base64 编码和解码

引言 在处理数据传输和存储时&#xff0c;经常需要对数据进行编码和解码。Base64 是一种常用的编码方式&#xff0c;它可以将二进制数据转换成64个可打印的字符&#xff0c;从而方便在文本环境中传输和存储。Arthas 提供了强大的 Base64 编码和解码功能&#xff0c;使得在 Jav…

OS:处理机进程调度

1.BackGround&#xff1a;为什么要进行进程调度&#xff1f; 在多进程环境下&#xff0c;内存中存在着多个进程&#xff0c;其数目往往多于处理机核心数目。这就要求系统可以按照某种算法&#xff0c;动态的将处理机CPU资源分配给处于就绪状态的进程。调度算法的实质其实是一种…

Django实战项目之进销存数据分析报表——第二天:项目创建和 PyCharm 配置

在上一篇博客中&#xff0c;我们讨论了如何搭建一个全栈 Web 应用的开发环境&#xff0c;包括 Python 环境的创建、Django 和 MySQL 的安装以及前端技术栈的选择。现在&#xff0c;让我们继续深入&#xff0c;学习如何在 PyCharm 中创建一个新的 Django 项目并进行配置。 一…

汇编 -- ARM汇编之 .inst指令与udf指令使用

ARM 汇编中的 .inst 与 udf 指令 技术背景 在ARM汇编编程中&#xff0c;有时需要使用一些标准汇编语言不支持的特殊指令&#xff0c;或需要在代码中插入断点或生成故意的异常以便进行调试和错误处理。.inst和udf指令在这些场景中非常有用。 .inst 指令 语法 .inst <mac…

对于品牌方来说,小红书探店应该怎么做?

小红书是中国最大的生活分享社交平台之一&#xff0c;它现在不仅仅是一个购物推荐平台&#xff0c;也是一个探店的好去处。 用户在网络上看到一家心仪的店铺&#xff0c;却又无法亲身到访&#xff0c;对店铺的产品存疑&#xff0c;这时候就会在小红书搜索具体的相关店铺信息。 …

MacOS解决安装pycurl的问题 no such file or directory: ‘/usr/lib/libcurl.@libext@‘

背景 芯片&#xff1a;MacBook Pro M3Mac OS: 14.1Python 2.7pip20.3.4 执行pip install pycurl7.19.0总是报错&#xff0c;例如&#xff1a; Looking in indexes: http://mirrors.aliyun.com/pypi/simple/ Collecting pycurl7.19.0Downloading http://mirrors.aliyun.com/p…

BUG ImportError: cannot import name ‘QAction‘ from ‘PySide6.QtWidgets‘

BUG ImportError: cannot import name ‘QAction’ from ‘PySide6.QtWidgets’ 环境 PySide6 6.7.2详情 在参考 PyQt5 的代码写 Pyside6 的右键菜单时遇到的错误。 错误代码 from PySide6.QtWidgets import QAction错误原因&#xff1a; 在PySdie6中&#xf…

【代码随想录】【算法训练营】【第58天 4】 [卡码104]建造最大岛屿

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 卡码网。 day 58&#xff0c;周四&#xff0c;ding~ 题目详情 [卡码104] 建造最大岛屿 题目描述 卡码104 建造最大岛屿 LeetCode类似题目827 最大人工岛 解题思路 前提&#xff1a; 思路&#xff1a; 重点…

Rust编程-模式匹配

模式&#xff1a; 用来匹配类型结构 组成&#xff1a;字面量、解体的数组、元组、枚举、结构体 、变量、通配符、占位符等组件组成 模式匹配的作用&#xff1a; 模式与match或其他工具配合使用可以更好控制流程 match分支&#xff1a; match 值 {模式 > 表达式 } match分支…