当前位置: 首页 > news >正文

游戏引擎学习第101天

回顾当前情况

昨天的进度基本上完成了所有内容,但我们还没有进行调试。虽然我们在运行时做的事情大致上是对的,但还是存在一些可能或者确定的bug。正如昨天最后提到的,既然现在时间晚了,就不太适合开始调试,所以今天我们将专门花时间逐步调试。

记得之前提到过几个bug问题。首先,我们没有正确地转换法线,因此在物体旋转时法线没有得到正确的调整。我们需要检查一下这个问题。其次,当我们使用球形法线贴图时,发现它似乎没有按照我们预期的方式弯曲,所以我们可能在这方面有个小bug。虽然离正确的法线贴图功能已经很近,但细节上还没有完全搞定。我们接下来的工作将集中在这些问题上,逐步修复。

开始思考如何转换法线

我们可以先考虑如何解决法线转换的问题。现在,我们已经设置好进行转换了。虽然在旋转时,法线始终指向上下方向,而这并不是我们真正想要的效果。我们已经准备好进行调试和修改,接下来需要处理的是法线的旋转,确保它们正确地朝向旋转后的位图方向。

首先,如果位图没有旋转,这个问题就不大,因为法线已经是朝着正确的方向。问题出现在位图旋转时,法线没有相应地进行旋转。为了支持这种情况,我们需要先构建一个路径,处理所有可能的情况,并确保法线旋转符合预期。随后,我们可以根据实际情况进行优化,去除不必要的处理步骤。例如,许多时候,位图并不会旋转,保持静止,因此没有必要每次都进行旋转法线的计算,这样的优化可以减少性能开销。

接下来,计划是构建一个旋转法线的路径,确保法线能随着位图旋转正确变换,之后再根据需要优化不必要的计算。

黑板:旋转法线(相当简单)

这个问题的关键在于正确地处理法线的旋转。可以把它看作是一个比较简单的数学问题。我们有一个贴图,其中包含了一些向量。当从贴图中提取出这些向量时,我们默认它们是按照贴图的原始方向来处理的,通常是按着贴图的坐标系(x轴和y轴)进行的。

假设贴图没有旋转的话,提取出的向量方向就是正常的。但是,如果图旋转贴了,比如旋转了45度,那么贴图中的向量方向应该也随之发生变化。简单来说,即使我们对贴图进行了旋转,提取出的贴图像素(Texel)仍然会按照原始的坐标系方向来显示,导致向量的方向不正确。为了纠正这一点,我们需要对这些法线向量进行旋转,使其与贴图的实际旋转保持一致。

因此,旋转法线的本质是利用贴图的坐标系来更新法线的方向,确保它们与贴图的旋转一致。

黑板:非均匀缩放有点复杂

当进行非均匀缩放时,X 和 Y 轴的缩放会有不同的变化,这种情况需要特别注意。具体来说,问题在于法线的变化。假设我们有一个向量,表示两个物体之间的关系。如果对 Y 轴进行缩放,想象法线会发生怎样的变化?法线会像被拉伸一样变长,就像如果它是一个点被缩放时一样,法线会沿着 Y 轴的方向进行伸展。

这就引出了一个问题:如果我们缩放一个表示表面的物体,法线是否应该按这种方式变化?这不仅仅是缩放表面的问题,还涉及如何处理法线方向和缩放比例的关系。法线的缩放需要根据具体的应用需求进行调整,而不是单纯地按比例伸缩。

黑板:假设我们有宝石的边缘

假设有一个形状,类似于一个宝石的边缘,法线大约指向45度的角度。如果对 Y 轴进行缩放,使其变长,那么原本代表法线的形状也会发生变化,变得拉长。也就是说,整体的形状会发生剪切,某些部分会被拉伸。

如果将法线按照相同的比例进行缩放,法线也会沿着 Y 轴方向伸展,但实际上,这种处理并不符合表面应有的变化。因为表面本身的法线,随着形状的拉伸,应该朝着相反的方向偏移。也就是说,表面的法线应该更多地指向下方,而不是继续沿着原先的方向。

因此,在支持非均匀缩放时,不能简单地将法线按与物体相同的方式进行缩放。要正确处理法线,需要考虑线性代数的知识,特别是在进行非均匀缩放时,法线的计算并不是直观的。对于没有线性代数背景的人来说,这种调整可能不容易理解,但它是必要的。
在这里插入图片描述

黑板:向量并不全是相同的

向量并非都是相同的,且有许多原因使得向量之间的行为不同。以 RGB 颜色值为例,特别是有预乘 alpha 的 RGBa 颜色值,它与非预乘 alpha 的 RGBa 颜色值在操作上就有所不同。预乘 alpha 允许进行线性操作,并且能够正常工作,而非预乘 alpha 则无法直接进行线性操作。这表明,向量不仅仅是将数字组合在一起的工具,它们的行为会根据具体的应用或操作不同而变化。

在更基础的层面,向量被视为一种处理数字的方式,但从理论角度来看,向量的行为可能因所做的操作类型不同而变化。预乘 alpha 可以被视作一个符合线性操作的向量,而非预乘的颜色值则不是这样,它们的行为和性质不一样,属于不同类型的数学对象,而不仅仅是编程对象。

在几何学中,构成形状的点可以看作是一种向量,它从原点指向特定的点,并且在坐标系变化时具有特定的行为。然而,法线是另一种类型的向量,它们的变换规则与点的向量不同,甚至有专门的术语来区分这两种向量类型,例如协变向量和逆变向量。对于法线来说,当应用变换时,它们的处理方式与点的向量不同,必须使用与点不同的变换规则。

如果有一个变换(例如伸长变换),当将点应用到该变换时,它们会按照预期进行变换,但法线的变换则需要使用不同的规则,以确保它们仍然符合法线的行为特性。因此,法线和点向量在处理变换时的行为不同,理解这一点对于正确处理非均匀缩放和其他变换非常重要。

协变向量(Covariant vector)和逆变向量(Contravariant vector)是描述向量如何在坐标变换下变化的两种不同类型的向量。它们的区别主要在于它们如何响应坐标系的变化。

1. 逆变向量(Contravariant Vector)

  • 定义:逆变向量是最常见的向量类型,通常是我们所说的普通向量。它们在坐标变换时会“反向”地变化。
  • 变化规则:如果进行坐标变换(例如旋转或缩放),逆变向量会按照坐标变换矩阵的逆来变化。换句话说,坐标系的基向量发生变化时,逆变向量会与基向量的变化方向相反。
  • 例子:在三维空间中,一个位于原点到点 P 的向量(例如位置向量)通常是逆变向量。它会随坐标系的变化(比如旋转)而变化。

2. 协变向量(Covariant Vector)

  • 定义:协变向量通常被用来表示梯度、法线等类型的量。它们的行为与逆变向量不同,当坐标系发生变化时,它们会“跟随”坐标系的变化。
  • 变化规则:协变向量在坐标变换时会直接按照坐标变换矩阵的方式变化。也就是说,协变向量的变化方式与基向量的变化方向一致。
  • 例子:法线向量就是一个协变向量的例子。如果一个表面发生变换(比如旋转或缩放),法线向量会随之变化,使得它始终与表面保持垂直。

总结区别

  • 逆变向量:变换时反向调整,通常用于描述位置、速度等物理量。
  • 协变向量:变换时直接调整,通常用于描述梯度、法线等方向性量。

直观解释

  • 想象一下在三维空间中有两个坐标系,A 和 B。假设 B 系统是经过 A 系统旋转或缩放得到的。在 B 系统中,如果你有一个逆变向量(比如位置向量),它会按反向变化来适应 B 系统的变化。而如果你有一个协变向量(比如法线向量),它会随坐标变换直接变化,以保持其在 B 系统中的正确方向。

这种区别在几何变换和物理学中很重要,尤其是在考虑如何处理变换时(如非均匀缩放和旋转)。

黑板:法线在线性代数中是不同的

在处理法线和点时,它们在数学上的处理方式不同,尤其是在向量的表示和变换上。点通常被表示为列向量(例如,px, py, pz),而法线则通常被表示为行向量。这种差异源于它们在坐标变换中的不同表现方式。

当处理变换时,点的变换通常使用变换矩阵直接进行,而法线的变换则需要使用变换矩阵的逆转置(inverse transpose)。也就是说,如果有一个作用于点的变换矩阵,要想正确地变换法线,必须使用该矩阵的逆转置。

这一点在线性代数中是非常常见的,尽管随着时间的推移,可能会忘记一些细节,但这种变换的规则对于正确处理法线和点在变换下的行为非常重要。

黑板:有时你得钻进数学的深坑α

可能需要深入探讨一些数学内容。虽然这可能会带来一些数学方面的挑战,但有时确实需要走出舒适区进行探索,因此可以尝试引入这个概念,并进行一些思考和讨论。

黑板:构造P向量

在构造这些P向量时,最初的情况是在二维空间中,有两个分量:px和py。这些是空间中的点,目的是将这些点转化为某种坐标系统中的点。为了实现这一点,构建了一个方法,将这些点的两个分量分别乘以x轴和y轴的向量,这样就得到了所谓的“屏幕空间点”。

这个方法的核心在于坐标系统的设定,其中x轴和y轴向量是二维向量,可以变化,并且通过旋转这些向量,可以使所有相关点的值随着旋转一起改变。这个旋转操作是通过旋转这些二维向量来实现的,形成了一个动态的网格,可以在其中进行缩放和旋转。这个系统的基础是支持纹理映射中的旋转和缩放的基础框架。

黑板:矩阵乘法

在矩阵形式中,首先要回顾一下矩阵乘法的基本操作。矩阵和向量是类似的,都是由数字组成的数组。通过回顾向量的点积,理解矩阵乘法其实是类似的过程。点积的计算方式是将对应的元素相乘后相加,这同样适用于矩阵乘法。

在矩阵与向量的乘法中,计算的基本步骤是对矩阵的每一行和向量的每一列进行点积。假设有一个2x2的矩阵,我们可以通过逐行逐列地进行点积,最终得到一个新的结果矩阵。这个过程对于任何矩阵乘法都适用,无论是矩阵与矩阵,还是矩阵与向量的乘法。

通过对矩阵的乘法理解,可以看到矩阵中的每一列代表一个坐标轴,进行矩阵运算时,实际上就是对这些坐标轴进行变换,比如旋转或缩放。矩阵允许以一种简洁的方式表示这些变换,而无需手动处理所有的标量量。

矩阵乘法的优势在于可以轻松地组合多个变换。例如,若有多个旋转和缩放操作,可以通过矩阵相乘来组合这些变换,从而得到一个新的变换矩阵,避免手动存储和操作多个变换。

此外,矩阵不仅支持乘法,还有逆运算、加法等操作。逆矩阵的计算比较复杂,但矩阵乘法本身是相对简单的,按照上述的点积方法就能完成。

总之,通过矩阵运算,可以高效地处理变换和操作,避免了手动管理多个标量量的麻烦。理解这些矩阵操作为后续处理更复杂的变换提供了基础。

矩阵的逆运算是线性代数中一个非常重要的概念。对于一个方阵 A A A,它的逆矩阵 A − 1 A^{-1} A1 满足以下关系:

A × A − 1 = A − 1 × A = I A \times A^{-1} = A^{-1} \times A = I A×A1=A1×A=I

其中, I I I 是单位矩阵。单位矩阵是一个对角线上全是 1,其他位置全是 0 的方阵。

1. 什么矩阵有逆矩阵?

并不是所有的矩阵都有逆矩阵。只有非奇异矩阵(即行列式不为零的矩阵)才有逆矩阵。如果矩阵的行列式 det ( A ) = 0 \text{det}(A) = 0 det(A)=0,那么该矩阵是奇异矩阵,没有逆矩阵。

2. 如何计算矩阵的逆?

对于一个 2 × 2 2 \times 2 2×2 矩阵:

A = [ a b c d ] A = \begin{bmatrix} a & b \\ c & d \end{bmatrix} A=[acbd]

其逆矩阵可以通过以下公式计算:

A − 1 = 1 det ( A ) [ d − b − c a ] A^{-1} = \frac{1}{\text{det}(A)} \begin{bmatrix} d & -b \\ -c & a \end{bmatrix} A1=det(A)1[dcba]

其中,行列式 det ( A ) \text{det}(A) det(A) 是:

det ( A ) = a d − b c \text{det}(A) = ad - bc det(A)=adbc

如果 det ( A ) = 0 \text{det}(A) = 0 det(A)=0,则矩阵没有逆矩阵。

对于更高维的矩阵,求逆的过程稍微复杂一些,通常通过高斯-约旦消元法或者伴随矩阵法来计算。

3. 高斯-约旦消元法(Gauss-Jordan Elimination)

高斯-约旦消元法是一种常用的求逆矩阵的算法,基本步骤如下:

  1. 将矩阵 A A A 和单位矩阵 I I I 拼接成一个增广矩阵:

    [ A ∣ I ] \left[ A | I \right] [AI]

  2. 通过一系列的行变换(行交换、行倍加、行线性组合等)将矩阵 A A A 化为单位矩阵 I I I,同时对单位矩阵 I I I 进行相应的变换。

  3. 最终增广矩阵的右半部分将是矩阵 A A A 的逆矩阵 A − 1 A^{-1} A1

4. 伴随矩阵法

伴随矩阵法通过求解矩阵的伴随矩阵(即矩阵的伴随矩阵是由矩阵的代数余子式构成的矩阵)来计算逆矩阵。具体步骤如下:

  1. 计算矩阵 A A A代数余子式矩阵 C C C

  2. 计算矩阵 C C C伴随矩阵 A ∗ A^* A,即将代数余子式矩阵进行转置。

  3. 计算矩阵 A A A 的行列式 det ( A ) \text{det}(A) det(A)

  4. 逆矩阵为:

    A − 1 = 1 det ( A ) A ∗ A^{-1} = \frac{1}{\text{det}(A)} A^* A1=det(A)1A

5. 数值求解

对于大矩阵,通常采用数值方法来计算逆矩阵,例如LU分解、QR分解等,这些方法更适合处理高维矩阵的求逆问题。

6. 逆矩阵的性质

  • 逆矩阵的唯一性:如果矩阵 A A A 有逆矩阵,则它的逆矩阵是唯一的。
  • 矩阵乘法的逆 ( A B ) − 1 = B − 1 A − 1 (AB)^{-1} = B^{-1}A^{-1} (AB)1=B1A1
  • 转置矩阵的逆 ( A T ) − 1 = ( A − 1 ) T (A^T)^{-1} = (A^{-1})^T (AT)1=(A1)T
  • 可逆性与行列式:矩阵可逆的充要条件是其行列式不为零,即 det ( A ) ≠ 0 \text{det}(A) \neq 0 det(A)=0

总之,矩阵的逆运算是解决线性方程组、进行几何变换等问题中的核心操作。掌握其计算方法对于理解和应用矩阵变换非常重要。

黑板:转置操作

转置和逆矩阵是两个常见的矩阵操作。我们先讨论转置操作和逆矩阵操作的区别及其意义。

1. 转置操作(Transpose)

转置是指将矩阵的行和列互换。具体来说,假设我们有一个矩阵 A A A

A = [ a b c d e f g h i ] A = \begin{bmatrix} a & b & c \\ d & e & f \\ g & h & i \end{bmatrix} A= adgbehcfi

它的转置 A T A^T AT 就是将矩阵中的行和列交换:

A T = [ a d g b e h c f i ] A^T = \begin{bmatrix} a & d & g \\ b & e & h \\ c & f & i \end{bmatrix} AT= abcdefghi

转置操作的核心是“镜像反射”沿着矩阵的主对角线(从左上到右下的对角线)。换句话说,矩阵 A A A 中的元素 A [ i ] [ j ] A[i][j] A[i][j] 在转置后会变为 A T [ j ] [ i ] A^T[j][i] AT[j][i]

转置操作的计算过程非常简单,可以通过重新排列矩阵元素实现。这种操作在矩阵计算中非常重要,因为它能够改变矩阵的排列结构,有助于在一些数学和物理问题中产生所需的变换。

例如,如果我们有一个矩阵表示了某些数据,转置操作可能会帮助我们从不同的角度理解这些数据或将其转换为适合进一步操作的形式。

2. 逆矩阵操作(Inverse Matrix)

逆矩阵是与矩阵相乘得到单位矩阵的矩阵。如果矩阵 A A A 有逆矩阵 A − 1 A^{-1} A1,则满足:

A × A − 1 = A − 1 × A = I A \times A^{-1} = A^{-1} \times A = I A×A1=A1×A=I

其中 I I I 是单位矩阵。并不是所有矩阵都有逆矩阵,只有当矩阵的行列式不为零时,矩阵才有逆矩阵(即非奇异矩阵)。如果行列式为零,矩阵就是奇异矩阵,不能计算其逆矩阵。

求逆矩阵的过程相对复杂,通常有两种常见方法:高斯-约旦消元法和伴随矩阵法。

  • 高斯-约旦消元法:通过对增广矩阵(原矩阵与单位矩阵拼接在一起)进行行变换,最终得到矩阵的逆。
  • 伴随矩阵法:先计算矩阵的代数余子式矩阵,然后取其转置得到伴随矩阵,最后通过行列式的倒数与伴随矩阵相乘得到逆矩阵。

逆矩阵在数学和工程应用中非常重要,尤其是在求解线性方程组、进行坐标变换、图形学中的变换等方面。

小结

  • 转置操作通过交换矩阵的行和列来改变矩阵的结构,简单易懂且易于实现。它的作用主要体现在矩阵的重排列,可以帮助我们在不同的坐标系之间进行转换。
  • 逆矩阵操作则是寻找一个矩阵,使得与原矩阵相乘得到单位矩阵。它通常用于解线性方程组或在多次变换的复合运算中恢复原始状态。

黑板:逆操作

逆矩阵的定义是:对于一个矩阵 A A A,它的逆矩阵 A − 1 A^{-1} A1 是一个矩阵,使得当 A A A A − 1 A^{-1} A1 相乘时,得到的是单位矩阵 I I I。单位矩阵是一个特殊的矩阵,其对角线上的元素为 1,其余元素为 0。单位矩阵有一个重要特性,它在与其他矩阵或向量相乘时,不会改变它们的值,即它是乘法中的“恒等元素”。

1. 单位矩阵

单位矩阵是一个非常特殊的矩阵,其结构如下:

I = [ 1 0 0 0 1 0 0 0 1 ] I = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix} I= 100010001

单位矩阵的作用类似于数字 1 在数值乘法中的作用。当一个矩阵与单位矩阵相乘时,它的值不会发生变化。例如,假设有一个向量 v = [ x y ] \mathbf{v} = \begin{bmatrix} x \\ y \end{bmatrix} v=[xy],如果将这个向量与单位矩阵相乘,结果就是:

I × v = [ x y ] I \times \mathbf{v} = \begin{bmatrix} x \\ y \end{bmatrix} I×v=[xy]

同样,矩阵乘法中的单位矩阵具有类似的性质,它不会改变与其相乘的矩阵或向量的值。

2. 逆矩阵的求解

逆矩阵的核心在于它能够“反转”一个矩阵的作用,使得矩阵与其逆矩阵相乘得到单位矩阵。假设有一个矩阵 A A A,其逆矩阵 A − 1 A^{-1} A1 满足:

A × A − 1 = A − 1 × A = I A \times A^{-1} = A^{-1} \times A = I A×A1=A1×A=I

为了找到矩阵 A A A 的逆矩阵,可以通过解方程的方式,利用矩阵的已知元素(如 A A A 中的元素)来推导出逆矩阵的元素。这就意味着需要解决一个方程组,其中包含了矩阵 A A A 中的元素和未知的逆矩阵元素。求解这个方程组的过程就是求逆矩阵的过程。

3. 乘法恒等元素和加法恒等元素

  • 乘法恒等元素:单位矩阵就是矩阵乘法中的恒等元素,它对其他矩阵或向量没有任何影响。
  • 加法恒等元素:与乘法恒等元素不同,加法恒等元素是一个全零矩阵,它在矩阵加法中充当类似角色,即与任何矩阵相加不会改变原矩阵。

小结

逆矩阵是矩阵运算中的一个重要概念,它使得矩阵能够“反转”其作用。通过逆矩阵和单位矩阵的性质,可以解决很多线性代数中的问题。求逆矩阵的过程通常涉及解方程组,计算复杂度较高,但它对于许多应用场景,如求解线性方程组、图形学中的变换等,都非常重要。

黑板:高斯消元法登场

解四个联立方程的过程通常被认为是一个麻烦的任务,尤其当需要处理多个方程时,可能会导致计算错误,因此很多人都会感到头疼。幸运的是,有一种方法叫做高斯消元法(Gaussian Elimination),它提供了一种相对简单的方式来求解方程组或计算矩阵的逆矩阵,尤其是在矩阵规模较小的情况下。

高斯消元法实际上不是用于计算大规模矩阵的逆或求解大规模方程组的理想选择。对于科学计算来说,矩阵的规模可能非常庞大,甚至达到数千、数万,甚至数百万个元素,这样的情况下使用高斯消元法就显得不切实际,因为它的时间复杂度是 O ( n 3 ) O(n^3) O(n3),处理大型矩阵时效率较低,并且在处理浮点数时存在数值不稳定性。

尽管如此,高斯消元法在解决简单的、规范化的 2x2 或更小规模的矩阵问题时仍然非常有效。在这种情况下,可以使用高斯消元法来进行矩阵求逆和方程求解。

矩阵最初并不是为计算机图形学而发明的,实际上它们是为了解决线性方程组而设计的。高斯消元法的出现正是为了解决含有多个未知数和方程的系统。在这种方法中,首先将方程的系数整理成一个矩阵,然后通过一系列的步骤(如消元)来求解未知数。每个方程中的系数可以视为矩阵中的元素,未知数则形成一个向量。这样,通过矩阵的乘法运算,就可以将原始的线性方程组转化为矩阵方程 A x = b Ax = b Ax=b,其中 A A A 是系数矩阵, x x x 是未知数向量, b b b 是常数向量。

这种方法大大简化了求解过程,使得解决复杂的方程组变得更加系统化和高效。高斯消元法通过逐步消元,将矩阵转化为上三角矩阵或对角矩阵,从而轻松求解未知数。
高斯消元法通过一系列的行变换,将矩阵转化为上三角矩阵或对角矩阵,最终求解线性方程组。下面通过一个简单的例子来演示高斯消元法的过程。

举例

让我们一步步进行高斯-乔丹消元法的求解。给定的方程组是:

3 x + y + z = 10 x + 2 y − 3 z = 10 x + y − z = 6 \begin{aligned} 3x + y + z &= 10 \\ x + 2y - 3z &= 10 \\ x + y - z &= 6 \end{aligned} 3x+y+zx+2y3zx+yz=10=10=6

第一步:将方程组写成增广矩阵

增广矩阵为:

[ 3 1 1 ∣ 10 1 2 − 3 ∣ 10 1 1 − 1 ∣ 6 ] \begin{bmatrix} 3 & 1 & 1 & | & 10 \\ 1 & 2 & -3 & | & 10 \\ 1 & 1 & -1 & | & 6 \end{bmatrix} 31112113110106

第二步:交换行,使得左上角为1

我们交换第1行和第2行,以便左上角为1:

[ 1 2 − 3 ∣ 10 3 1 1 ∣ 10 1 1 − 1 ∣ 6 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ 3 & 1 & 1 & | & 10 \\ 1 & 1 & -1 & | & 6 \end{bmatrix} 13121131110106

第三步:消去第一列中的其他数值

  1. 第2行:用第2行减去第1行的3倍得第二行,使得第2行第一列变为0:
    R 2 → R 2 − 3 R 1 R_2 \rightarrow R_2 - 3R_1 R2R23R1
    [ 1 2 − 3 ∣ 10 3 − 3 ∗ 1 1 − 3 ∗ 2 1 − 3 ∗ ( − 3 ) ∣ 10 − 3 ∗ ( 10 ) 1 1 − 1 ∣ 6 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ \textcolor{red}{3-3*1} & \textcolor{red}{1-3*2} & \textcolor{red}{1-3*(-3)} & | & \textcolor{red}{10 - 3*(10)} \\ 1 & 1 & -1 & | & 6 \end{bmatrix} 1331121321313(3)110103(10)6
    得到:
    [ 1 2 − 3 ∣ 10 0 − 5 10 ∣ − 20 1 1 − 1 ∣ 6 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ 0 & -5 & 10 & | & -20 \\ 1 & 1 & -1 & | & 6 \end{bmatrix} 101251310110206

  2. 第3行:用第1行减去第3行,使得第3行第一列变为0:
    R 3 → R 3 − R 1 R_3 \rightarrow R_3 - R_1 R3R3R1
    [ 1 2 − 3 ∣ 10 0 − 5 10 ∣ − 20 1 − 1 1 − 2 − 1 − ( − 3 ) ∣ 6 − 10 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ 0 & -5 & 10 & | & -20 \\ \textcolor{red}{1-1} & \textcolor{red}{1-2} & \textcolor{red}{-1-(-3)} & | & \textcolor{red}{6 - 10} \end{bmatrix} 101125123101(3)1020610
    得到:
    [ 1 2 − 3 ∣ 10 0 − 5 10 ∣ − 20 0 − 1 2 ∣ − 4 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ 0 & -5 & 10 & | & -20 \\ 0 & -1 & 2 & | & -4 \end{bmatrix} 100251310210204

第四步:将第2行的主元化为1

将第2行除以-5,使得第2行的主元变为1:
R 2 → 1 − 5 R 2 R_2 \rightarrow \frac{1}{-5} R_2 R251R2
[ 1 2 − 3 ∣ 10 0 / ( − 5 ) − 5 / ( − 5 ) 10 / ( − 5 ) ∣ − 20 / ( − 5 ) 0 − 1 2 ∣ − 4 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ \textcolor{red}{0/(-5)} & \textcolor{red}{-5/(-5)} & \textcolor{red}{10/(-5)} & | & \textcolor{red}{-20/(-5)} \\ 0 & -1 & 2 & | & -4 \end{bmatrix} 10/(5)025/(5)1310/(5)21020/(5)4

得到:
[ 1 2 − 3 ∣ 10 0 1 − 2 ∣ 4 0 − 1 2 ∣ − 4 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ 0 & 1 & -2 & | & 4 \\ 0 & -1 & 2 & | & -4 \end{bmatrix} 1002113221044

第五步:消去第二列中的其他数值

  1. 第3行:用第2行加到第3行,使得第3行第二列变为0:
    R 3 → R 3 + R 2 R_3 \rightarrow R_3 + R_2 R3R3+R2
    [ 1 2 − 3 ∣ 10 0 1 − 2 ∣ 4 0 + 0 − 1 + 1 2 + ( − 2 ) ∣ − 4 + 4 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ 0 & 1 & -2 & | & 4 \\ \textcolor{red}{0+0} & \textcolor{red}{-1+1} & \textcolor{red}{2+(-2)} & | & \textcolor{red}{-4+4} \end{bmatrix} 100+0211+1322+(2)1044+4
    得到:
    [ 1 2 − 3 ∣ 10 0 1 − 2 ∣ 4 0 0 0 ∣ 0 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ 0 & 1 & -2 & | & 4 \\ 0 & 0 & 0 & | & 0 \end{bmatrix} 1002103201040

  2. 第1行:用第2行的2倍去减去第1行,使得第1行第二列变为0:
    R 1 → R 1 − 2 R 2 R_1 \rightarrow R_1 - 2R_2 R1R12R2
    [ 1 − 2 ∗ 0 2 − 2 ∗ 1 − 3 − 2 ∗ ( − 2 ) ∣ 10 − 2 ∗ 4 0 1 − 2 ∣ 4 0 0 0 ∣ 0 ] \begin{bmatrix} \textcolor{red}{1-2*0} & \textcolor{red}{2 - 2*1} & \textcolor{red}{-3-2*(-2)} & | & \textcolor{red}{10-2*4} \\ 0 & 1 & -2 & | & 4 \\ 0 & 0 & 0 & | & 0 \end{bmatrix} 120002211032(2)20102440
    得到:
    [ 1 0 1 ∣ 2 0 1 − 2 ∣ 4 0 0 0 ∣ 0 ] \begin{bmatrix} 1 & 0 & 1 & | & 2 \\ 0 & 1 & -2 & | & 4 \\ 0 & 0 & 0 & | & 0 \end{bmatrix} 100010120240

第六步:解释最终矩阵

矩阵现在已经是简化行最简形式。方程组变为:

x + z = 2 y − 2 z = 4 0 = 0 ( 无新信息 ) \begin{aligned} x + z &= 2 \\ y - 2z &= 4 \\ 0 &= 0 \quad (\text{无新信息}) \end{aligned} x+zy2z0=2=4=0(无新信息)

从第一个方程:
x = − z + 2 x = -z + 2 x=z+2

从第二个方程:
y = 2 z + 4 y = 2z + 4 y=2z+4

因此,解为:
x = − z + 2 , y = 2 z + 4 , z = z x = -z + 2, \quad y = 2z + 4, \quad z = z x=z+2,y=2z+4,z=z
其中, z z z 是自由变量(可以取任意值)。因此,解的形式是:

( x , y , z ) = ( − z + 2 , 2 z + 4 , z ) (x, y, z) = (-z + 2, 2z + 4, z) (x,y,z)=(z+2,2z+4,z)

这是该方程组的通解。

黑板:求解多个未知数的方程

当解决多个未知数的方程组时,首先要做的是消去项。通过消去项,可以将方程组简化为一个较为简单的形式,最终得出一个未知数的值。具体方法是,首先尽可能消除掉不需要的项,使得每个方程只包含一个未知数。接着,通过除以系数得到该未知数的解,然后可以将这个解代入其他方程中,逐步反向求解其他未知数,直到所有未知数的解都得到。

这种解决方法是通过规范化的过程实现的。其核心思想是将求解的步骤转化为一系列可以执行的规则,从而简化了实际的计算和推导过程。在数学中,这个过程是非常常见的,尤其是在处理线性方程组时,消元法和回代法是常用的技术。

总结来说,解决多元方程组的基本思路是消去多余项、简化方程,然后逐步求解每个未知数的值。

黑板:我们完全陷入了数学的深坑β

有时,可能会陷入数学的思维模式中,一旦进入这种状态,就会完全专注于数学问题,不再关注其他方面。这个过程有时会导致思维的偏离,可能会突然忘记自己原本要表达的内容。即使如此,通常还是会回到原本的话题,并且最终会再次提到自己之前的思考内容。

在数学过程中,尤其是在解决方程和矩阵问题时,重点是理解这些概念如何应用,并逐步把复杂的数学操作转化为规范的规则和步骤。最终,虽然有时会迷失在数学的深思中,但最终还是会回到解决问题的目标上,并继续推进思维的逻辑。

黑板:你可以自由地加或乘任何两条含有相同项的方程

如果要构建一个矩阵,只包含未知数的系数,可以从方程出发。假设有两个方程,分别是方程的左边和右边,表示的是未知数的关系。对于这两个方程,知道它们的左边和右边是相等的。

如果有两个方程,可以将它们加在一起,这是完全合法的操作。只要在方程的两边加上相同的量,这个等式依然成立。因为左边和右边是相等的,所以可以自由地对它们进行加法操作。这样,方程的两边仍然保持平衡。

此外,还可以将方程的两边都乘以相同的数值,这同样是合法的。比如,如果将方程的左边和右边都乘以2,依然不会改变方程的平衡,因为在两边做相同的操作,方程的本质没有变化。可以随意进行这些加法和乘法操作,只要遵循等式的规则,结果依然是有效的。

黑板:我们可以对矩阵的行列进行正则化操作

在处理矩阵时,可以通过对矩阵的行和列进行操作来规范化矩阵。通过对行进行操作,可以逐步消去矩阵中的某些项。例如,假设有一个矩阵的第一行表示系数,而我们希望通过操作第二行来消去某些元素。具体来说,如果想要消去某个元素(例如H),可以考虑如何将第一行的某个元素(例如a)调整成与H相等。为了达到这个目的,可以通过加上适当的倍数来实现消去。

这种操作通常是通过除以某个系数,计算出需要加的数值,从而使得矩阵中的特定元素变为零。这个过程的核心是通过行操作将矩阵简化,逐步消去不需要的项。

黑板:使用数字清晰演示高斯消元法

在进行矩阵操作时,通过消去特定的项,可以简化矩阵。假设有一个矩阵,如:

( 5 2 3 1 7 6 10 4 9 ) \begin{pmatrix} 5 & 2 & 3 \\ 1 & 7 & 6 \\ 10 & 4 & 9 \end{pmatrix} 5110274369

想要消去某些值,比如消去第二行和第三行的某个元素。为此,可以考虑如何通过行操作使得某个元素变为零。比如,要消去第一行的第二个元素(2),可以计算出需要多少倍的第一行元素来使得第二行中的某个值消失。具体来说,这个倍数就是第二行要减去的倍数,这个值为2。然后,可以将第一行乘以2,再与第二行进行相减,从而消去第二行中的元素。

这样处理后,原本的矩阵经过行操作后就变成了新的矩阵,其中第二行的第一个和第二个元素被消去,而第三行的最后一个元素变成了0。这个操作可能会消去多个元素,有时候可能会不小心消去不该消去的项,但这是行操作中常见的现象。

通过行操作,可以逐步消去矩阵中的元素,最终将矩阵简化到只剩下一个项。这一项对应着最后的未知数,这个过程的目的是通过消去其他项来逐步求解未知数,从而得到最终的解。如果按照这种方法进行操作,就能够逐步减少方程中的未知数,直到只剩下一个最终的解。

黑板:然后你可以将最后剩下的项除以目标数

一旦消去矩阵中的其他项,最后剩下的项可以通过目标值进行除法运算,得到最终的解。虽然有时可以进一步消去项,但并非每次都高效,因为有些操作可能需要对其他行进行调整。关键在于,当矩阵中的一些项被消去后,可以通过将最后剩下的项除以目标值来得到所需结果,最终可能得到一个单位矩阵。

整个过程中,重要的是理解如何通过行操作来简化矩阵。具体操作包括:可以将一个行的倍数加到另一个行上,或者通过乘以负数再加到另一行上,最终消去不需要的项。这些行操作可以帮助消除矩阵中的某些成员。

通过这样的行操作,问题变得更加计算机友好,因为这是一堆数字,操作相对简单,易于编程实现。这样的线性方程求解方法可以通过程序实现,比如高斯消元法(Gaussian elimination)。接下来,可以更明确地讨论如何在计算机中实现这一过程。

黑板:我们希望能够通过矩阵乘法得到单位矩阵

目标是通过高斯消元法来将一个矩阵转化为单位矩阵(1, 0, 0, 1)。要实现这一点,需要通过一系列行操作,使得矩阵的左侧部分转化为单位矩阵,同时右侧部分产生结果。在这个过程中,关键是通过高斯消元法操作对原始矩阵进行变换,使得当进行乘法运算时,能够得到最终的单位矩阵。

其中一个常见的策略是将高斯消元法应用到矩阵的同时,也操作一个初始单位矩阵。这样,当矩阵转化为单位矩阵时,右侧的矩阵就会变成原始矩阵的逆矩阵。虽然这种方法可能需要一定的技巧,但基本概念是通过一系列的行操作使得左边变成单位矩阵,右边的矩阵最终变为所需的逆矩阵。

黑板:高斯消元法的常规解法

高斯消元法(Gaussian Elimination)如何用于求解线性方程组,并逐步解释了如何通过矩阵操作来找出方程的解。主要的步骤包括:

  1. 矩阵与向量乘法:如果已知矩阵 A 和向量 X,可以通过矩阵与向量的乘法得到结果 AX。但当不知道向量 X 时,需要求解方程 AX = B

  2. 高斯消元法:高斯消元法是一种通过一系列行操作将矩阵转化为上三角矩阵的算法。这个过程可以将方程组中的未知数逐步消去,最终得到解。

  3. 消去步骤

    • 假设有一个方程组 AX = B,通过消去系数矩阵的某些元素(比如通过对行进行加减运算),可以逐步简化方程。
    • 首先,通过乘以某个系数并加到另一行,来消去某个元素。
    • 然后继续对矩阵进行行操作,直到得到一个上三角矩阵。
  4. 求解未知数:在得到上三角矩阵后,可以通过代回的方式逐步求解未知数。这个过程是从最后一行开始,逐步代入前面的行。

  5. 矩阵的逆:通过高斯消元法还可以求解矩阵的逆。实际操作中,除了求解线性方程组外,也可以在过程中同时计算矩阵的逆(通过将单位矩阵附加到原矩阵旁边进行行操作)。

  6. 注意事项:高斯消元法虽然对于小规模矩阵非常有效,但对于大规模或病态矩阵(即条件数大的矩阵),其数值稳定性较差。因此,在实际应用中,通常会采用其他更加稳定的数值方法,如迭代法。

黑板:不幸的是我们没有完全讲到逆转置

这段内容主要讲解了矩阵的逆与转置的概念,尤其是如何通过矩阵的逆来解决线性方程组的问题。

  1. 逆矩阵的定义与作用

    • 逆矩阵是指如果有一个矩阵 A,那么它的逆矩阵 A⁻¹ 满足 A * A⁻¹ = I,其中 I 是单位矩阵。逆矩阵的核心作用是,它可以帮助解决方程组,特别是通过逆矩阵来从已知的 AB 计算出未知的 X
    • 逆矩阵的应用不局限于理论,它可以用来解线性方程组。例如,对于方程 AX = B,如果已知矩阵 A 和向量 B,则可以通过乘以 A 的逆矩阵来求解 X。也就是说,X = A⁻¹ * B
  2. 方程组的解法

    • 之前的重点是如何给定 AX 来计算 B,也就是正向运算(如 AX = B)。然而,在这段内容中,转向了反向解法,即给定 AB,如何计算 X
    • 当我们知道了逆矩阵的存在后,可以通过逆矩阵将方程两边同时乘以 A⁻¹,从而求解 X。这个过程帮助解决了线性方程组中的未知数,特别是在变换坐标系时尤为重要。
  3. 坐标系的变换与逆矩阵的应用

    • 之前的例子讨论了坐标系之间的转换:给定一个坐标系中的点 P,如何通过变换矩阵 A 将其转换到另一个坐标系中。这个过程使用了类似 P' = A * P 的关系式。
    • 在这个讨论中,逆矩阵的作用是逆向操作,即给定变换后的点 P' 和变换矩阵 A,通过求解 P = A⁻¹ * P',可以将点 P' 从变换后的坐标系映射回原始坐标系。
  4. 矩阵的逆转置关系

    • 另一个重要话题是矩阵的逆转置。当矩阵的逆等于其转置时,这会有特别的意义。尽管具体的条件和应用还未深入探讨,但可以初步理解为在某些情况下,逆矩阵和转置矩阵可能具有相等的关系。
  5. 高斯消元法与逆矩阵的计算

    • 计算逆矩阵的过程会用到高斯消元法,但由于计算的复杂性,讨论没有完全展开。高斯消元法是通过行变换将矩阵简化为上三角矩阵的过程,从而帮助计算出逆矩阵。

对于反转2x2矩阵,使用简单的余子式方程非常高效

对于求解二阶矩阵的逆矩阵,一个简单的余子式(cofactor)方程是非常高效的。具体来说,二阶矩阵的逆矩阵可以通过一个简单的公式来求得,公式如下:

设矩阵 A 为:

A = [ a b c d ] A = \begin{bmatrix} a & b \\ c & d \end{bmatrix} A=[acbd]

它的逆矩阵 A⁻¹ 可以通过以下公式计算:

A − 1 = 1 a d − b c [ d − b − c a ] A^{-1} = \frac{1}{ad - bc} \begin{bmatrix} d & -b \\ -c & a \end{bmatrix} A1=adbc1[dcba]

其中,ad - bc 是矩阵 A 的行列式。如果行列式不等于零,则矩阵 A 是可逆的,逆矩阵就是上述公式中的结果。

这个方法通过使用余子式和行列式的概念来计算逆矩阵,适用于二阶矩阵。对于更高阶的矩阵,通常需要更复杂的计算方法,如高斯消元法或者行列式的展开。

消元法中的所有步骤都可以表示为一个矩阵。从M开始,乘以所有这些矩阵,得到单位矩阵。所以这些矩阵相乘就是逆矩阵。将它们全部与单位矩阵相乘就得到了逆矩阵。是这个技巧吗?

在讨论高斯消元法时,可以通过矩阵的乘法来表示每一个消元步骤,最终通过这些步骤矩阵的乘积可以得到单位矩阵。换句话说,通过这些矩阵的乘积得到的结果就是矩阵的逆。

首先,考虑高斯消元法中的一个操作。例如,假设我们有一个矩阵,目标是通过某种操作将矩阵中的元素变为零。这个操作可以通过构造一个矩阵来实现,这个矩阵在乘以原矩阵后,能产生想要的结果。具体来说,如果我们要对矩阵的某一行进行变换,例如将某行的一个元素乘以某个系数并加到另一行上,那么我们可以构造一个矩阵来实现这个变换。这个矩阵会与原矩阵相乘,产生预期的结果。

通过这种方法,可以将每一步消元操作转化为矩阵乘法,并最终得到单位矩阵。而这些操作矩阵的乘积就构成了逆矩阵。这是通过矩阵乘法实现矩阵求逆的一种方式。

然而,在实际操作中,这个过程并不容易直观理解。例如,想要通过矩阵表示某个特定的消元操作时,可能需要构造一个矩阵,它在某一行上产生特定的变换,但这个过程并不总是简单。特别是在实际构建矩阵时,可能会出现疑惑,例如如何确保在进行行变换时保持矩阵的其他部分不变,这需要深思熟虑和一些反复的推敲。

总结来说,矩阵的逆是通过逐步的行变换实现的,而每一个行变换都可以用一个矩阵来表示,最终这些矩阵的乘积给出的是逆矩阵。不过,这个过程涉及到复杂的矩阵运算,需要一定的线性代数基础来理解和实现。

为了找逆矩阵,我们难道不能通过负角度旋转并按最初缩放的倒数缩放来做吗?

在讨论矩阵的逆时,可以通过旋转负角度并按最初的缩放因子倒数进行缩放来构造逆矩阵。这种方法通常用于图形学中,因为有时直接反转矩阵比计算逆矩阵要简单。然而,这种方法只适用于已经知道矩阵的来源的情况,因为有时我们并不总是知道矩阵的构成。

如果矩阵是由缩放和旋转构成的,并且已经知道缩放因子和旋转角度,那么可以通过分别计算逆缩放矩阵和逆旋转矩阵来得到矩阵的逆。缩放矩阵是一个对角矩阵,其中对角线元素为缩放因子,其他位置为零。如果要得到逆矩阵,则缩放因子的倒数作为新矩阵的对角线元素。旋转矩阵的逆则是其转置矩阵,即旋转的逆操作。

对于旋转矩阵的逆,可以通过数学推导得出。当旋转矩阵表示的是坐标轴的旋转时,逆矩阵可以通过交换矩阵的列来得到。这是因为旋转矩阵的列向量是单位向量,并且它们是正交的。通过点积计算,可以验证转置矩阵确实是旋转矩阵的逆。

此外,逆矩阵的计算涉及到如何处理旋转和缩放的组合。对于旋转矩阵,点积可以验证旋转矩阵和其转置的关系。对于缩放矩阵,只需将对角线元素倒数,就可以得到缩放的逆。

总结来说,旋转矩阵的逆通常是其转置,而缩放矩阵的逆是通过将其对角线元素倒数来得到的。这种方法能够有效地简化矩阵求逆过程,尤其是在已知矩阵结构的情况下。

我记得我是把单位矩阵放在原始矩阵旁边,逐步对每个进行操作

讨论了矩阵求逆的过程。首先,通过理解矩阵乘以单位矩阵的性质,即矩阵与单位矩阵相乘得到原矩阵,建立了矩阵求逆的基础。接着,介绍了高斯消元法(Gaussian elimination)来将矩阵通过一系列步骤转化为单位矩阵,进而求得其逆矩阵。

具体来说,假设有一个矩阵 A A A,其乘以单位矩阵 I I I 等于自身,即 A × I = A A \times I = A A×I=A,这个过程是矩阵乘法的基本法则之一。然后,通过消去矩阵的每一项,逐步将原矩阵变为单位矩阵。在这个过程中,消元后的矩阵的另一部分就会变成矩阵 A A A 的逆矩阵。

然而,在执行这个过程时,存在一些困惑的地方。一个问题是,经过消元后,为什么最终得到的矩阵一定是正确的逆矩阵。此时需要再次仔细推导消元过程,确保每一步都符合数学原理。尽管有些部分令人感到困惑,但总体思路是通过高斯消元法将原矩阵转化为单位矩阵,从而找到其逆矩阵。

如果你有一个矩阵,比如 int[2][2],变量是abcd,难道你不能仅仅交换a和d并把c和b取负吗?

讨论了如何通过对一个 2x2 矩阵进行操作来求逆。假设矩阵是:

[ a b c d ] \begin{bmatrix} a & b \\ c & d \end{bmatrix} [acbd]

如果按照提议,交换 a a a d d d,并将 b b b c c c 取负,得到新的矩阵:

[ d − b − c a ] \begin{bmatrix} d & -b \\ -c & a \end{bmatrix} [dcba]

接下来,通过计算矩阵的行列式,即做点积,得到:

a d − ( − b ) ( − c ) = a d − b c ad - (-b)(-c) = ad - bc ad(b)(c)=adbc

然后观察到,结果 a d − b c ad - bc adbc 不等于 1,因此这并不是单位矩阵,也不能直接作为逆矩阵。为了矩阵的逆成立,行列式的值必须等于 1,否则无法得到正确的逆矩阵。

总结来说,直接交换矩阵的元素并取负并不能保证得到逆矩阵,必须通过正确的行列式计算和消元步骤来验证逆矩阵的正确性。

如果你将A和I写在一起,然后应用一堆操作,你在计算T3T2T1 A和T3T2T1 I。因为你最后得到单位矩阵,T3T2T1A = I。所以T3T2T1 = A^-1。因此T3T2T1 I = A^-1

有一种方法来计算矩阵的逆,即将矩阵 A A A 和单位矩阵 I I I 放在一起,应用一系列操作。这个方法的基本思路是,经过一系列操作(比如高斯消元),将矩阵 A A A 转换为单位矩阵 I I I。在这个过程中,对矩阵 I I I 同时应用相同的操作。最终,矩阵 A A A 变成了单位矩阵,而矩阵 I I I 变成了 A A A 的逆矩阵。

这些操作步骤可以称为 t 1 , t 2 , t 3 t_1, t_2, t_3 t1,t2,t3 等,它们代表了将矩阵 A A A 转换为单位矩阵的过程。根据这个过程,得出的结论是,操作 t 1 , t 2 , t 3 t_1, t_2, t_3 t1,t2,t3 作用于单位矩阵时,结果就是矩阵 A A A 的逆。换句话说,假设操作将 A A A 变成了单位矩阵,那么这些操作实际上也得到了矩阵 A A A 的逆,因为它们能够将单位矩阵转换为 A − 1 A^{-1} A1

这种思路通过高斯消元来说明如何得到矩阵的逆。当矩阵 A A A 被消元为单位矩阵时,相应的步骤会使单位矩阵变成 A A A 的逆。

相关文章:

游戏引擎学习第101天

回顾当前情况 昨天的进度基本上完成了所有内容,但我们还没有进行调试。虽然我们在运行时做的事情大致上是对的,但还是存在一些可能或者确定的bug。正如昨天最后提到的,既然现在时间晚了,就不太适合开始调试,所以今天我…...

将Docker容器打包成镜像提交

前言 Docker 是一个开源软件,也是一个开放平台,用于开发应用、交付(shipping)应用、运行应用。 Docker允许用户将基础设施(Infrastructure)中的应用单独分割出来,形成更小的颗粒(容…...

JVM——堆的回收:引用计数发和可达性分析法、五种对象引用

目录 引用计数法和可达性分析法 引用计数法: 可达性分析算法: 五种对象引用 软引用: 弱引用: 引用计数法和可达性分析法 引用计数法: 引用计数法会为每个对象维护一个引用计数器,当对象被引用时加1&…...

沪深300股指期权能对股指期货进行完全套保吗?

锦鲤三三每日分享期权知识,帮助期权新手及时有效地掌握即市趋势与新资讯! 沪深300股指期权能对股指期货进行完全套保吗? 沪深300股指期权是以沪深300指数为标的物的期权,而沪深300股指期货则是以该指数作为标的的期货合约。 理…...

tomcat html乱码

web tomcat html中文乱码 将html文件改成jsp <% page language"java" contentType"text/html; charsetUTF-8" pageEncoding"UTF-8"%>添加 <meta charset"UTF-8">...

全星QMS软件的功能如何助力企业进行精细化的质量管理

全星QMS软件的功能如何助力企业进行精细化的质量管理 在当今竞争激烈的市场环境中&#xff0c;企业要想脱颖而出&#xff0c;精细化的质量管理是关键。全星QMS软件系统凭借其全面的功能和强大的技术支持&#xff0c;为企业提供了一站式的质量管理解决方案&#xff0c;助力企业…...

BPMN.js 与 DeepSeek 集成:打造个性化 Web 培训项目的秘诀

在数字化时代&#xff0c;Web培训项目的需求日益增长&#xff0c;特别是对于程序员群体&#xff0c;他们寻求高效、灵活的方式来提升自己的技能。本文将深入探讨如何评估BPMN.js与DeepSeek集成方案&#xff0c;以满足开发Web培训项目的需求。 BPMN.js 的优势 BPMN.js是一个专…...

鸢尾花分类

以下是一个通过Python编程语言实现“机器学习”小项目的详细教程案例,该项目使用经典的鸢尾花(Iris)数据集进行分类任务: 项目:鸢尾花分类 项目目标 通过机器学习模型,根据鸢尾花的花瓣和萼片的长度和宽度,预测其所属的种类。 实现步骤 导入必要的库 Python复制 import …...

SpringCloud系列教程:微服务的未来(二十三)SpringAMQP快速入门、Work Queues、Fanout交换机

前言 Spring AMQP是Spring框架中用于与消息中间件&#xff08;如RabbitMQ&#xff09;进行交互的一个项目&#xff0c;它简化了消息发送、接收以及消息处理的过程。通过Spring AMQP&#xff0c;开发者可以快速实现基于RabbitMQ的消息传递系统。本文将介绍Spring AMQP的快速入门…...

快速排序

目录 什么是快速排序&#xff1a; 图解&#xff1a; 递归法&#xff1a; 方法一&#xff08;Hoare法&#xff09;&#xff1a; 代码实现&#xff1a; 思路分析&#xff1a; 方法二&#xff08;挖坑法&#xff09;&#xff1a; 代码实现&#xff1a; 思路分析&#xff1a; 非递…...

【C++ 真题】P1824 进击的奶牛

P1824 进击的奶牛 题目描述 Farmer John 建造了一个有 N N N&#xff08; 2 ≤ N ≤ 1 0 5 2 \leq N \leq 10 ^ 5 2≤N≤105) 个隔间的牛棚&#xff0c;这些隔间分布在一条直线上&#xff0c;坐标是 x 1 , x 2 , ⋯ , x N x _ 1, x _ 2, \cdots, x _ N x1​,x2​,⋯,xN​&a…...

HCIA项目实践--RIP的拓展配置

9.4.7 RIP的拓展配置 &#xff08;1&#xff09;RIPV2的手工认证 RIPv2 的手工认证是增强网络安全性的手段。管理员手动配置密钥&#xff0c;路由器在收发 RIPv2 路由更新消息时&#xff0c;会对消息中的认证信息进行检查。发送方添加密钥&#xff0c;接收方用预设密钥验证。若…...

MyBatis映射文件 <resultMap> 元素详解与示例

引言 <resultMap> 是 MyBatis 中最核心的映射配置元素&#xff0c;用于解决数据库字段与 Java 对象属性之间的复杂映射问题&#xff0c;尤其是字段名不一致、嵌套对象关联、集合映射等场景。ResultMap 的设计思想是&#xff0c;对简单的语句做到零配置&#xff0c;对于复…...

leetcode刷题记录(一百零二)——45. 跳跃游戏 II

&#xff08;一&#xff09;问题描述 45. 跳跃游戏 II - 力扣&#xff08;LeetCode&#xff09;45. 跳跃游戏 II - 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。每个元素 nums[i] 表示从索引 i 向后跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] …...

2004-2016年各省煤炭基础储量数据

2004-2016年各省煤炭基础储量数据 1、时间&#xff1a;2004-2016年 2、指标&#xff1a;行政区划代码、地区、年份、煤炭基础储量(亿吨) 3、范围&#xff1a;31省 4、来源&#xff1a;国家统计局、统计年鉴 5、指标解释&#xff1a;煤炭基础储量是指在特定区域内&#xff…...

【含开题报告+文档+PPT+源码】基于spring boot的固定资产管理系统

开题报告 本研究论文提出了一种基于SpringBoot框架构建的全面且高效的固定资产管理系统&#xff0c;旨在优化企业内部的固定资产全生命周期管理流程。该系统集成了员工权限管理、业务流程处理及数据分析于一体&#xff0c;实现了员工便捷的登录注册功能&#xff0c;并通过安全…...

数据结构-链式二叉树

文章目录 一、链式二叉树1.1 链式二叉树的创建1.2 根、左子树、右子树1.3 二叉树的前中后序遍历1.3.1前(先)序遍历1.3.2中序遍历1.3.3后序遍历 1.4 二叉树的节点个数1.5 二叉树的叶子结点个数1.6 第K层节点个数1.7 二叉树的高度1.8 查找指定的值(val)1.9 二叉树的销毁 二、层序…...

C++中接口与继承的区别(自我学习用)

继承&#xff08;Inheritance&#xff09;和 接口&#xff08;Interface&#xff09;是面向对象编程&#xff08;OOP&#xff09;中的两种不同概念&#xff0c;虽然在 C 中没有像 Java 那样的 interface 关键字&#xff0c;但可以通过 纯虚函数 来实现接口的概念。让我们详细比…...

vue2拖拽式页面构建

在Vue 2中构建一个拖拽式页面&#xff0c;你可以使用第三方库如vuedraggable&#xff0c;它是基于Sortable.js的一个Vue组件&#xff0c;非常适合用于实现拖拽功能。 步骤 1: 安装vuedraggable 首先&#xff0c;你需要安装vuedraggable。在你的Vue项目中&#xff0c;运行以下命…...

ASUS/华硕天选3 FA507R FA707R 原厂Win11 21H2家庭版系统 工厂文件 带ASUS Recovery恢复

华硕工厂文件恢复系统 &#xff0c;安装结束后带隐藏分区&#xff0c;带一键恢复&#xff0c;以及机器所有的驱动和软件。 支持型号&#xff1a;FA507RC, FA507RE, FA507RM, FA507RW, FA707RC, FA707RE, FA707RM, FA707RW, FA507RH, FA707RH, FA507RR, FA707RR 系统版本&…...

部署onlyoffice后,php版的callback及小魔改(logo和关于)

作为这篇博文的补充CentOS9 安装Docker+Dpanel+onlyoffice(https、更改字体、字号、去除限制)的避坑笔记,现在继续… 本次主要内容有:php中callback的调用、自签证书调用callback遇到SSL certificate problem: unable to get local issuer certificate问题、修改onlyoffic…...

轻松打造专属音乐库:Alger Music本地部署与远程访问全流程解析

文章目录 前言1. 安装Docker2. 简单使用演示3. 安装cpolar内网穿透4. 配置公网地址5. 配置固定公网地址 前言 嗨&#xff0c;大家好&#xff01;今天我要给大家安利一款超级棒的第三方网抑云音乐播放器。这款神器不仅颜值超高、功能强大&#xff0c;还能让你彻底告别那些烦人的…...

redis集群的分片技术

Redis 集群模式通过 数据分片&#xff08;Sharding&#xff09; 技术将数据分布到多个节点上&#xff0c;从而实现横向扩展和高性能。以下是 Redis 集群分片技术的详细介绍&#xff1a; 1. 数据分片的基本原理 Redis 集群将整个数据集划分为 16384 个哈希槽&#xff08;Hash S…...

OA审批 / 流程管理 :流程设计/审批人设置/选择节点的审批人 | Java获取树形用户列表

文章目录 引言I 树形用户列表VO通用树状节点类型通用树状节点对象II 获取树形用户列表准备部门信息和用户信息III 其他相关表结构组织机构引言 流程设计/审批人设置/选择节点的审批人 树形显示用户列表(安装组织机构层级显示) 接口返回的树形用户的数据结构I 树形用户列表VO …...

【Pandas】pandas Series case_when

Pandas2.2 Series Computations descriptive stats 方法描述Series.align(other[, join, axis, level, …])用于将两个 Series 对齐&#xff0c;使其具有相同的索引Series.case_when(caselist)用于根据条件列表对 Series 中的元素进行条件判断并返回相应的值 pandas.Series.…...

.NET 9.0 的 Blazor Web App 项目,自定义日志 TLog V2 使用备忘

一、TLog V1 使用静态数据库上下文&#xff0c;优点是速度快&#xff0c;缺点是内存占用大&#xff0c;参见 .NET 9.0 的 Blazor Web App 项目、Bootstrap Blazor 组件库、自定义日志 TLog 使用备忘_navigationmanager.tobaserelativepath-CSDN博客 二、 TLog V2 改为 依赖注入…...

数据仓库与数据挖掘记录 二

1.数据仓库的产生 从 20 世纪 80 年代初起直到 90 年代初,联机事务处理一直是关系数据库应用的主流。然而,应用需求在不断地变化,当联机事务处理系统应用到一定阶段时,企业家们便发现单靠拥有联机事务处理系统已经不足以获得市场竞争的优势,他们需要对其自身业务的运作以及整个…...

SolidWorks速成教程P3-1【零件 | 第一节】——特征成型介绍拉伸凸台/基体与设计树

零件是由特征构成的&#xff0c;所以零件学习也叫做特征学习。 特征命令&#xff0c;我们可以认为是将二维草图变成三维实体的过程&#xff0c;学习完成后我们就能画出很多东西了&#xff0c;比如画一台手机的外形&#xff0c;学完后我们一起画一个手机支架&#xff0c;来熟练…...

vscode插件Remote - SSH使用教程

Remote - SSH 是一款非常实用的 Visual Studio Code (VSCode) 扩展插件,它允许开发者通过SSH连接到远程服务器,并像在本地一样进行代码编辑和调试。这意味着你可以直接在VS Code中打开位于远程机器上的文件夹,并利用本地安装的VS Code功能,如语法高亮、智能感知、Git集成等…...

sqli_labs_master Less-8 时间盲注,boolen盲注 获取数据库中的表、列

获取当前数据库名 import requestsdef inject_database(url):namemax_length20 # 假设数据库名称最大长度为20# ASCII范围&#xff1a;数字、字母、下划线&#xff08;_&#xff09;low{a: 97, z: 122, A: 65, Z: 90, 0: 48, 9: 57, _: 95}high{97: a, 122: z, 65: A, 90: Z,…...

Android Studio:RxJava事件流Observable

一、什么是“事件流”&#xff1f; 简单来说&#xff0c;事件流 就是数据从一个地方&#xff08;发布者&#xff09;传递到另一个地方&#xff08;订阅者&#xff09;的过程&#xff0c;像是一个“流水线”。发布者发布事件&#xff08;数据&#xff09;&#xff0c;订阅者则在…...

Influxdb学习 - TSM存储

InfluxDb为什么这么快 InfluxDB 之所以在时序数据场景下表现出色,主要得益于其专为时序数据优化的架构设计和多层次的性能优化策略 专为时序设计:TSM 引擎、列式存储、时间分区等特性直接针对时序数据痛点。写入优化:内存缓存 + 批量刷盘 + 高压缩率,最大化吞吐。查询加速…...

监控系统磁盘 I/O 性能的命令

iostat -x -k 1 是一个用于监控系统磁盘 I/O 性能的命令&#xff0c;下面详细解释该命令以及其输出各项的含义。 命令参数解释 iostat&#xff1a;这是一个用于报告中央处理器&#xff08;CPU&#xff09;统计信息和磁盘输入 / 输出统计信息的工具。 -x&#xff1a;显示扩展的…...

NumPy中生成和堆叠数组、生成切片的特殊对象:np.r_ np.c_ np.s_

在NumPy中有三个特殊的对象&#xff0c;非常好用&#xff1a; np.r_&#xff1a;按行连接两个数组&#xff0c;也就是将两个数组垂直堆叠。np.c_&#xff1a;按列连接两个数组&#xff0c;也就是将两个数组水平堆叠。np.s_&#xff1a;生成用于切片的slice对象。 下面详细介绍…...

js计算当(月/年)工作日(除去节假日)时间进度

js封装文件 // 获取当年的节假日12个月的数据 let holidaysArr [[1, 4, 5, 11, 12, 18, 19, 25, 26, 27, 28, 29, 30, 31], // 1月[1, 2, 3, 4, 5, 6, 9, 15, 16, 22, 23], // 2月[], // 3月[4, 5, 6, 12, 13, 19, 20, 26], // 4月[1, 2, 3, 4, 5, 10, 11, 17, 18, 24, 25, …...

zyNo.22

常见Web漏洞解析 命令执行漏洞 1.Bash与CMD常用命令 &#xff08;1&#xff09;Bash 读取文件&#xff1a;最常见的命令cat flag 在 Bash 中&#xff0c;cat 以及的tac、nl、more、head、less、tail、od、pr 均为文件读取相关命令&#xff0c;它们的区别如下&#xff1a; …...

服务器绑定 127.0.0.1 和 0.0.0.0 的区别

前言 IP 地址实际上并不是分配给计算机的&#xff0c;而是分配给网卡的&#xff0c;因此当计算机上存在多块网卡时&#xff0c;每一块网卡都会有自己的 IP 地址。 绑定 127.0.0.1 是绑定到 lookback 这个虚拟的本地回环接口&#xff0c;该接口只处理本机上的数据&#xff0c;…...

系统思考—团队学习

“一个人的成长是从问题中学习&#xff0c;而组织的成长是从结构中进化。” —— 彼得圣吉 看似松散的团队学习结构&#xff0c;回头一看&#xff0c;你早已成长了许多。今天和小伙伴们聊起2024年&#xff0c;才发现很多改变&#xff0c;都是在不经意间发生的。 从最初的探索…...

《Python百炼成仙》21-30章(不定时跟新)

第廿一章 列表开天可变序列初成 不周山的擎天玉柱裂开蛛网纹路&#xff0c;山体内部传出数据结构崩塌的轰鸣。叶军踏着《数据结构真解》残页凌空而立&#xff0c;手中薛香的本命玉尺泛起列表操作的幽光&#xff1a; 补天石序列 [五色石] * 9补天石序列[3] 息壤 # 引发链式变…...

element-ui时间组件同一个月内选择/30天内选择

element-ui时间组件同一个月内选择/30天内选择 同一个月 <el-date-picker v-model"time" type"datetimerange"range-separator"至" start-placeholder"开始时间"value-format"timestamp" :picker-options"pickerO…...

【大模型】阿里云百炼平台对接DeepSeek-R1大模型使用详解

目录 一、前言 二、DeepSeek简介 2.1 DeepSeek 是什么 2.2 DeepSeek R1特点 2.2.1 DeepSeek-R1创新点 2.3 DeepSeek R1应用场景 2.4 与其他大模型对比 三、阿里云百炼大平台介绍 3.1 阿里云百炼大平台是什么 3.2 阿里云百炼平台主要功能 3.2.1 应用场景 3.3 为什么选…...

微信小程序配置3 配置sass

1. 在config。json文件里面的setting配置“sass” 2. 改你需要的页面后缀名为scss。 3.查看页面即可看到样式。...

应用层优秀的共享民宿物联网框架该怎么选?

有一说一&#xff0c;应用层优秀的物联网框架通常能帮助提升用户体验、提高运营效率、节能减排等等优势&#xff0c;很多老板也很注重这个层面的设计和打磨&#xff0c;那么对于选择应用层优秀的共享民宿物联网框架时&#xff0c;大家可以从哪几个关键因素进行考量呢&#xff1…...

macOS 上部署 RAGFlow

在 macOS 上从源码部署 RAGFlow-0.14.1&#xff1a;详细指南 一、引言 RAGFlow 作为一款强大的工具&#xff0c;在人工智能领域应用广泛。本文将详细介绍如何在 macOS 系统上从源码部署 RAGFlow 0.14.1 版本&#xff0c;无论是开发人员进行项目实践&#xff0c;还是技术爱好者…...

postman登录cookie设置

1.设置环境变量&#xff0c; 定义变量存放共享的登录信息 如Cookie 2.登录接口编码test脚本获取cookie信息 let jsessionidCookie pm.cookies.get("JSESSIONID");if (jsessionidCookie) {let cookie "JSESSIONID" jsessionidCookie "; Admin-Tok…...

如何在Linux中设置定时任务(cron)

在Linux系统中&#xff0c;定时任务是自动执行任务的一种非常方便的方式&#xff0c;常常用于定期备份数据、更新系统或清理日志文件等操作。cron是Linux下最常用的定时任务管理工具&#xff0c;它允许用户根据设定的时间间隔自动执行脚本和命令。在本文中&#xff0c;我们将详…...

激光工控机在精密制造中的应用与优势

在精密制造中&#xff0c;激光工控机可以用于许多场景例如 激光切割与雕刻&#xff1a;用于金属、塑料、陶瓷等材料的精密切割和雕刻&#xff0c;适用于汽车、航空航天、电子等行业&#xff1b;可实现复杂图案和高精度加工&#xff0c;满足微米级精度要求。 激光焊接&#xf…...

conda的创建

1. 确认 conda 已安装 在使用 conda 创建环境之前&#xff0c;需要确保 conda 已经成功安装在你的系统中。你可以通过在命令行中输入以下命令来检查&#xff1a; conda --version如果已经安装&#xff0c;命令行会显示 conda 的版本号&#xff1b;若未安装&#xff0c;你可以…...

python视频爬虫

文章目录 爬虫的基本步骤一些工具模拟浏览器并监听文件视频爬取易错点一个代码示例参考 爬虫的基本步骤 1.抓包分析&#xff0c;利用浏览器的开发者工具 2.发送请求 3.获取数据 4.解析数据 5.保存数据 一些工具 requests, 用于发送请求&#xff0c;可以通过get&#xff0c;p…...

cv2.Sobel

1. Sobel 算子简介 Sobel 算子是一种 边缘检测算子&#xff0c;通过对图像做梯度计算&#xff0c;可以突出边缘。 Sobel X 方向卷积核&#xff1a; 用于计算 水平方向&#xff08;x 方向&#xff09; 的梯度。 2. 输入图像示例 假设我们有一个 55 的灰度图像&#xff0c;像素…...