精华内容
下载资源
问答
  • 这一篇文章和大家聊聊向量。向量这个概念我们在高中就接触到了,...写成一列的称为列向量,例如:写成一行则是行向量:为了方便并且统一,在当前以及以后的文章当中,我们使用小写字母来表示列向量,列向量的转置表...

    这一篇文章和大家聊聊向量

    向量这个概念我们在高中就接触到了,它既指一个点在空间中的坐标,也表示一个有向线段,如果我们加入复数概念的话,它还能表示一个数。在线性代数当中,向量就是指的n个有次序的数a1, a2,...an组成的数组。

    向量可以写成一行,也可以写成一列。写成一列的称为列向量,例如:

    97fff7ec8240a552747f30663c5eb3d1.png

    写成一行则是行向量:

    2461dec613d7ef6fe515c999df7d431a.png

    为了方便并且统一,在当前以及以后的文章当中,我们使用小写字母来表示列向量,列向量的转置表示行向量,例如

    3898968e2d33d5967e6de9693e5d337e.png

    既然向量可以表示点,点可以表示空间,那么自然向量也可以表示空间。所以我们可以把三维空间用向量表示:

    0bb6f5f515f32fd08278bf4dd576900d.png

    既然我们可以用向量的集合表示空间,自然也可以用向量的集合来表示平面。表示平面的方式很简单,就是在向量当中限制一些条件,只保留满足条件的向量,比如三维空间当中的平面可以表示成:

    92f78783ae0982964104a42365da0487.png

    同样,我们可以拓展到多维空间当中,一个n维空间可以用向量表示成:

    8bfd0f6b63a798e9d78d80a1dde28782.png

    n维空间当中的平面可以表示成:

    2d501ab01e3b0c5a73778737ba5abc63.png

    如上定义的平面称为n维空间当中n-1维的超平面。因为超过3维的空间,我们很难想象出它的物理意义,所以称为超平面。

    我们可以把若干个向量组合到一起,这样的组合称为向量组,其实就是矩阵。我们可以把一个m * n的矩阵,看成是n个m维的列向量组合而成的向量组。之前我们介绍的Ax=0的齐次线性方程组的解,当R(A) < n时,它是无限多个n维列向量的向量组。

    有了向量组之后,我们看下一个概念。假设A是一个m个n维向量的向量组:

    7c0a6aee94e38780907eae3d37e92e53.png

    b是另一个n维的向量。如果存在一组数:

    0bb247c9331e9725b204a37773a9c391.png

    使得:

    bb8da9ddec273ce967b939db34dbbc06.png

    那么,我们称向量b能被向量组A线性表示

    这一点能够成立,其实也就是方程组:

    c5ea8d706fd3f0b2a16a04884fb63f83.png

    有解。如果我们将它展开,其实就是我们之前介绍的非齐次线性方程组。我们之前的文章当中已经证明过了,要使得该方程组有解,必须要满足:R(A) = R(A, b),这样,我们就把向量组和之前的线性方程组联系起来了。

    如果存在不全为0的数:k1, k2, ... kn 使得:

    15c7a77719b985e86c287a2c7ed81497.png

    那么则称向量组A是线性相关的,否则是线性无关的。一般情况下,我们说线性无关或者线性相关,都是指n >= 2的情况。我们很容易看出,对于两向量来说线性相关,其实就是指的两向量成比例。如果是三个向量,则是三向量共面

    如果一个向量组A线性相关,我们假设a1向量的系数k_1不为零,那么根据线性相关的定义,我们可以写出:

    6a59d2db1c0446f5ca6f445ce8dc7184.png

    也就是说a1向量能够被A组当中其他向量线性表示。反之,如果A组向量之中有一个向量能够被其他向量线性表示,那么就说明A组向量线性相关。

    我们再换一种理解方式,如果将A组向量

    27c39075180885c0d6fcfccf56b998fe.png

    看做是矩阵

    2143520d389e3c9abdf3682dccf85a54.png

    向量组A线性相关,就是齐次线性方程组Ax=0有非零解。我们之前介绍齐次线性方程组的时候曾经介绍过,齐次线性方程组要有非零解的条件是R(A) < n。如果R(A) = n,那么齐次线性方程组没有非零解,也就是说向量组A线性无关

    这样一来,我们就把上一篇文章当中介绍的线性方程组是否有解的问题串联起来了。记不清楚的同学可以点击下方链接回顾上篇文章:线性代数精华——讲透矩阵的初等变换与矩阵的秩

    到这里,我们关于向量组和线性相关的概念就差不多介绍完了。不过向量组当中还有一些很好用的性质,简单列举一下:

    1. 如果向量组

    b758b6d449d0ff1bd184cbb347829013.png

    线性相关,那么向量组

    68cf2cacb44f5ae0f923c4517793d33b.png

    也线性相关。反之,如果B线性无关,那么A也一定线性无关。

    2. n个m维向量组成的向量组,当m 小于 n 时,一定线性相关。另外,n+1个n维向量一定线性相关。

    3. 如果向量组

    b758b6d449d0ff1bd184cbb347829013.png

    线性无关,向量组

    f118e4b4c4063dff47c6d9991b317345.png

    线性相关。那么向量b必然可以被向量组A线性表示,并且表示的方式唯一。

    以上三个特性都很直观,这里就不一一证明了。

    这里说的线性相关都是绝对的线性相关,但是在机器学习领域,由于数据之间存在误差,所以我们很少使用绝对的线性相关。相反,我们会用向量之间的相似度来衡量向量之间的相关性。

    在线性模型当中,我们会分析特征和预测结果的相关性,如果相关性不高,那么说明这个特征非常弱,或者效果很差,如果很强,则说明这个特征指导意义很高。我们也会分析特征之间的相关性,如果某两个特征相关性很高,说明它们提供的信息差不多,对于模型来说其实提供了非常近似的信息,很可能并不会带来正面助益,反而带来误差或者影响。这时候可以考虑去除多余的特征,或者使用一些降维算法,来降低特征的维度。

    向量空间

    最后,我们来简单介绍一下向量空间。向量空间的定义很简单,其实就是一个全体向量的集合。我们把全体n维向量组成的集合,称作是n维向量空间。

    假设V是一个向量空间,存在r个向量:

    50e01a9963053ded3ce747a6f6587a95.png

    并且满足以下条件:

    1. a1, a2 ... ar 线性无关

    2. V中任一向量都可以用a1, a2, ... ar 线性表示。

    那么我们称向量组a1, a2, ..., ar为向量空间V的一个基,r称为向量空间V的维数,并称V为r维的向量空间。如果把向量空间V也看成是向量组,那么V的维数其实就是这个向量组的秩。

    有了基的概念之后,我们就可以表示向量空间当中所有的向量。假设空间V的基是a1, a2, ..., ar

    ,对于任一向量x,都有唯一的一个表示:

    5221fffd71b9dd61f91cd44f188c2ed9.png

    数组

    03f2f0e411f49181c13568a85666a7fe.png

    就是向量x在基a1, a2, ..., ar中的坐标

    对于n维向量空间Rn,我们取它的单位坐标向量组:

    24860d7cfe77b82dfa41d709604ac599.png

    那么x就可以表示成:

    e3c547780cdd343b27222af75e52b24e.png

    其中的

    a7b902a1bc68d52447ef417c65333d80.png

    也就是x向量在各个维度上的分量,因此

    24860d7cfe77b82dfa41d709604ac599.png

    就称为是空间Rn中的自然基。

    今天的文章就是这些内容,其实并没有什么特别的,只是将我们串联了一些我们之前学过的知识,以及明确了线性代数领域对于向量以及相关性的概念。

    如果觉得有所收获,还请右下角点个“关注”吧。

    展开全文
  • 潮流计算(运用vector实现矩阵的运算,包括返回一个矩阵,运用复数库对复数进行操作),这个程序最大的特点就是将各种操作封装函数,不必所有的代码都在主函数里面.
  • Z=r* exp(i*theta) z=r*exp(theta) 2创建复矩阵 创建复矩阵的方法有两种 (1)如同一般的矩阵一样以前面介绍的几种方式输入矩阵 例如:A=[3+5,2+39*exp(i*6,23*exp(33i) (2)可将实虚矩阵分开创建,再写成和的形式 例如 ...
  • 令 则(1)式也可以写成其中:(2)系数按照原来顺序排列成一个n级矩阵A: 则二次型(1)可以写成 对称矩阵A称为二次型 的矩阵.A的秩称为二次型的秩 .例如:其对应的矩阵则 的秩为2.二次型与其矩阵是一一对应的,因此可...

    870ae66ad1d8ef31343dfb46cd378cbf.png

    1.二次型的概念

    定义 n元二次齐次多项式

    称为n元二次型,简称为二次型.

    • 为复数,称为复二次型;
    • 为实数,称为实二次型.

    则(1)式也可以写成

    其中:(2)系数按照原来顺序排列成一个n级矩阵A:

    则二次型(1)可以写成
    • 对称矩阵A称为二次型
      的矩阵.
    • A的秩称为二次型
      的秩
      .

    例如:

    1782f055cd32a73530ea2b800cb767f5.png

    其对应的矩阵

    91445778747b8b1a406a3676f6c61c84.png

    的秩为2.

    d1eba28d56985b79d9542ba7698386c5.png

    二次型与其矩阵是一一对应的,因此可借助实对称矩阵来研究实二次型.

    炫云:线性代数28——对称矩阵及正定矩阵,正定性zhuanlan.zhihu.com
    b8114c2c46925d3d164aa254bdc60478.png

    2.二次型的化简

    二次曲线

    77c999e63d7b0f7e9438b511b742a9f2.png

    记为

    ,作坐标变换(正交变换)
    ,即

    3b6e5c0a485d8d41e921c0b0dabb4dd4.png

    方程为

    ,即
    ,若:

    fa4409142cd2e00f2bdc75ba3455c2f0.png

    则方程化为入

    ,此时很容易判断二次曲线的类型.
    炫云:线性代数33——线性变换及对应矩阵zhuanlan.zhihu.com
    b8114c2c46925d3d164aa254bdc60478.png

    对于 n元二次型

    线性变换

    记为

    ,

    其中

    ,若C可逆,称X=CY为可逆线性变换,并称
    A与B合同.

    展开全文
  • 四元数 四元数(quaternion)可以看作中学时学的复数的扩充,它有三个虚部。形式如下: 四元数(quaternion)可以看作中学时学的复数的扩充,它有三个虚部。...[公式] ,可以写成 [公式] 4*4变换矩阵 四元数到4*4矩阵 ...

    齐次坐标

    关于为什么用齐次坐标(4维)表示三维空间中的点和向量,可以参考什么是齐次坐标系?为什么要用齐次坐标系?,此处不再赘述
    只需知道,齐次坐标(x,y,z,0)(x,y,z,0)可以表示三维空间向量,$(x,y,z,w)&可以表示空间点&(x/w,y/w,z/w)&,w常取值为1。这些齐次坐标均可以使用下文提到的4*4矩阵进行变换

    4*4变换矩阵

    参考“为什么DirectX里表示三维坐标要建一个4*4的矩阵?”
    矩阵是用于表示变换而不是坐标的。为什么变换要使用一个4×4的矩阵而不是3×3的矩阵呢?

    平移

    如何平移一个三维空间中的点呢,只需对于点坐标中的每个分量(x,y,z)对应轴上的平移距离相加即可。
    例如,点p1(x1,y1,z1)在X轴Y轴以及Z轴上分别平移Δx,Δy,Δz到新的点p2(x2,y2,z2),那么我们只需在坐标对应的分量上加上这些增量就可以确定点p2的坐标了。
    在这里插入图片描述
    x2=x1+Δxx2 = x1 + Δx
    y2=y1+Δyy2 = y1 + Δy
    z2=z1+Δzz2 = z1 + Δz

    旋转

    需要从以下几个方面来描述一个旋转:

    1. 旋转轴
    2. 旋转方向
    3. 旋转角度

    在这里,我们假设点p需要绕Z轴顺时针旋转β度。
    在这里插入图片描述
    如图所示,我们的点P1(x1,y1,z1)以Z轴位轴顺时针旋转β度之后来到了点P2(x2,y2,z2)。那么根据三角函数公式(推导过程见上文链接)可以计算出P1点的具体坐标了
    x2=cosβx1+sinβy1x2=\cosβ\cdot{x1}+\sinβ\cdot{y1}
    y2=cosβy1sinβx1y2=\cosβ\cdot{y1}-\sinβ\cdot{x1}
    z2=z1z2=z1
    类似的,绕x轴逆时针旋转θ角:
    x2=x1x2=x1
    y2=cosθy1sinθz1˙y2=\cosθ\cdot{y1}-\sinθ\dot{z1}
    z2=sinθy2+cosθz1˙z2=\sinθ\cdot{y2}+\cosθ\dot{z1}
    绕y轴逆时针旋转θ角:
    x2=cosθx1+sinθz1x2=\cosθ\cdot{x1}+\sinθ\cdot{z1}
    y2=y1y2=y1
    z2=sinθx1+cosθz1z2=-\sinθ\cdot{x1}+\cosθ\cdot{z1}
    绕z轴逆时针旋转θ角:
    x2=cosθx1sinθy1x2=\cosθ\cdot{x1}-\sinθ\cdot{y1}
    y2=sinθx1+cosθy1y2=\sinθ\cdot{x1}+\cosθ\cdot{y1}
    z2=z1z2=z1

    3×3矩阵和旋转

    在现实中常常使用矩阵(由m × n个标量组成的长方形数组)来表示诸如平移、旋转以及缩放等线性变换。当两个变换矩阵A和B的积为P=AB时,则变换矩阵P相当于A和B所代表的变换。举一个例子,若A为旋转矩阵,B为平移矩阵,则矩阵P就能够实现旋转和平移变换。不过需要注意的是,矩阵乘法不符合交换律,因此AB和BA并不相等。
    上文提到的绕z轴逆时针旋转θ角的变换,可以以矩阵形式描述为:
    [x2y2z2]=[cosθsinθ0sinθcosθ0001][x1y1z1]\begin{bmatrix}x2\\y2\\z2\end{bmatrix}= \begin{bmatrix} \cosθ&-\sinθ&0\\ \sinθ&\cosθ&0\\ 0&0&1 \end{bmatrix} \begin{bmatrix}x1\\y1\\z1\end{bmatrix}
    相似的,绕x轴逆时针旋转θ角矩阵:
    [1000cosθsinθ0sinθcosθ]\begin{bmatrix} 1&0&0\\ 0&\cosθ&-\sinθ\\ 0&\sinθ&\cosθ \end{bmatrix}
    绕y轴逆时针旋转θ角矩阵:
    [cosθ0sinθ010sinθ0cosθ]\begin{bmatrix} \cosθ&0&\sinθ\\ 0&1&0\\ -\sinθ&0&\cosθ \end{bmatrix}

    4×4矩阵,引入平移

    3×3矩阵解决了旋转变换的表示问题,但是对于下面所示的,旋转和平移的复合,却展现了局限性
    x2=ax1+by1+cz1x2 = a\cdot{x1} + b\cdot{y1} + c\cdot{z1}
    x2=x1+Δxx2 = x1 + Δx
    y2=dx1+ey1+fz1y2 = d\cdot{x1} + e\cdot{y1} + f\cdot{z1}
    y2=y1+Δyy2 = y1 + Δy
    z2=gx1+hy1+iz1z2 = g\cdot{x1} + h\cdot{y1} + i\cdot{z1}
    z2=z1+Δzz2 = z1 + Δz
    平移和旋转之间很重要的一个区别,那就是平移的表达式中带有常量Δx,而无论是旋转的表达式还是矩阵等式中都不存在这样一个常量能够与之对应。解决这个问题的方法,就是用4×4矩阵来实现。

    4×4矩阵与齐次坐标

    三维矢量添加了第四个分量,这样之前的三维矢量(x,y,z)就变成了四维的(x,y,z,w),这样由4个分量组成的矢量便被称为齐次坐标。需要说明的是,齐次坐标(x,y,z,w)等价于三维坐标(x/w,y/w,z/w),因此只要w分量的值是1,那么这个齐次坐标就可以被当作三维坐标来使用,而且所表示的坐标就是以x,y,z这3个值为坐标值的点。
    因此,为了和4×4矩阵相乘,我们的P1点坐标就变成了(x1,y1,z1,1)。而矩阵等式也变成了下面这个样子:
    [x2y2z21]=[abcdefghijklmnop][x1y1z11]\begin{bmatrix}x2\\y2\\z2\\1\end{bmatrix}= \begin{bmatrix}a&b&c&d\\e&f&g&h\\i&j&k&l\\m&n&o&p\end{bmatrix} \begin{bmatrix}x1\\y1\\z1\\1\end{bmatrix}
    其中,4×4矩阵的左上角3×3部分等同于上文的3×3矩阵,d、h、l代表x、y、z方向上的平移,m、n、o一般为0,p为1。这个4*4矩阵代表旋转和平移的复合(先旋转后平移)。
    一个4×4的平移矩阵如下所示:
    [x2y2z21]=[100Δx010Δy001Δz0001][x1y1z11]\begin{bmatrix}x2\\y2\\z2\\1\end{bmatrix}= \begin{bmatrix}1&0&0&Δx\\0&1&0&Δy\\0&0&1&Δz\\0&0&0&1\end{bmatrix} \begin{bmatrix}x1\\y1\\z1\\1\end{bmatrix}

    c++实现

    //point3D.h
    class Point3D
    {
    public:
    	double x, y, z;
    	Point3D();
    	Point3D(double x, double y, double z)
    	{
    		this->x = x;
    		this->y = y;
    		this->z = z;
    	}
    };
    
    #pragma once
    //matrix.h
    #include "Point3D.h"
    class Matrix
    {
    public:
    	Matrix();
    	Matrix(int m[16]);
    	~Matrix();
    	Point3D Mutiply(Point3D ptVec);
    private:
    	double p[4][4];
    };
    
    //matrix.cpp
    #include "Matrix.h"
    Matrix::Matrix()
    {}
    
    Matrix::Matrix(int m[16])
    {
    	int y, x, i = 0;
    	for (y = 0; y < 4; y++)
    	{
    		for (x = 0; x < 4; x++)
    		{
    			p[y][x] = m[i];
    		}
    	}
    }
    
    Matrix::~Matrix()
    {}
    
    Point3D Matrix::Mutiply(Point3D ptVec)
    {
    	Point3D ptRes;
    	ptRes.x = p[0][0] * ptVec.x + p[0][1] * ptVec.y + p[0][2] * ptVec.z + p[0][3];
    	ptRes.y = p[1][0] * ptVec.x + p[1][1] + ptVec.y + p[1][2] + ptVec.z + p[1][3];
    	ptRes.z = p[2][0] * ptVec.x + p[2][1] * ptVec.y + p[2][2] * ptVec.z + p[2][3];
    	return ptRes;
    }
    

    四元数

    四元数的定义

    四元数(quaternion)可以看作中学时学的复数的扩充,它有三个虚部。形式如下:
    q=w+xi+yj+zk\vec{q}=w+xi+yj+zk
    可以写成:
    q=s+v\vec{q}=\vec{s}+\vec{v}
    以矩阵形式记录其四个分量:
    q=[wxyz]Tq=\begin{bmatrix}w&x&y&z\end{bmatrix}^T
    这四个分量满足:
    q2=w2+x2+y2+z2=1|q{|^2} = {w^2} + {x^2} + {y^2} + {z^2} = 1

    四元数的基本运算

    参考四元数和旋转-知乎,默认讨论右手系。

    乘法运算

    q1=s1+v1\vec{q_1}=s_1+\vec{v_1}q2=s2+v2\vec{q_2}=s_2+\vec{v_2}则:
    q1q2=[w1x1y1z1][w2x2y2z2]=[w1w2x1x2y1y2z1z2x1w2+w1x2+y1z2z1y2y1w2+w1y2+z1x2x1z2z1w2+w1z2+x1y2y1x2]=s1s2v1v2+s1v2+s2v1+v1×v2\vec{q_1}\vec{q_2}=\begin{bmatrix}w1\\x1\\y1\\z1\end{bmatrix}*\begin{bmatrix}w2\\x2\\y2\\z2\end{bmatrix}\\=\begin{bmatrix}w1w2-x1x2-y1y2-z1z2\\x1w2+w1x2+y1z2-z1y2\\y1w2+w1y2+z1x2-x1z2\\z1w2+w1z2+x1y2-y1x2\end{bmatrix}\\=s_1s_2-\vec{v_1}\vec{v_2}+s_1\vec{v_2}+s_2\vec{v_1}+\vec{v_1}×\vec{v_2}
    注意,此处讨论的是四元数乘法,不同于向量点乘或叉乘。

    共轭四元数

    一个四元数q=s+v\vec{q}=s+\vec{v}的共轭(用qˉ\bar{\vec{q}}表示)为qˉ=sv\bar{\vec{q}}=s-\vec{v}
    一个四元数和它的共轭的积等于该四元数与自身的点乘,也等于该四元数长度的平方。即:
    qqˉ=qˉq=qq=q2=q2\vec{q}\bar{\vec{q}}=\bar{\vec{q}}\vec{q}=\vec{q}\cdot\vec{q}=||\vec{q}||^2=q^2

    四元数的逆

    一个非零四元数q\vec{q}的逆为q1=qˉq2\vec{q}^{-1}=\frac{\bar{\vec{q}}}{\vec{q}^2}。显然qq1=1\vec{q}\vec{q}^{-1}=1

    四元数表示旋转

    三维空间中的旋转可以被认为是一个函数φφ,从R3\Bbb{R}^3到自身的映射。函数φφ表示的一个旋转,旋转过程中保持向量长度(lengths)、向量夹角(angles)和handedness不变。
    (handedness和左右手坐标系有关,例如左手坐标系中向量旋转后,仍要符合左手坐标系规则)
    由下面公式给出的函数,可以表示旋转
    φq(P)=qPq1φ_q(\vec{P})=\vec{q}\vec{P}\vec{q}^{-1}
    这里q\vec{q}是一个非零四元数,函数的参数P\vec{P}可以看作三维空间中的点(即一个实部或标量部分为0的四元数)。

    由旋转到四元数

    可以找到一个单位四元数q\vec{q},对应于绕旋转轴A\vec{A}旋转θθ角度的旋转变换:
    q=s+v=s+tA=cosθ2+Asinθ2\vec{q}=s+\vec{v}\\=s+t\vec{A}\\=\cos{\frac{θ}{2}}+\vec{A}\sin{\frac{θ}{2}}
    其中,A\vec{A}是单位向量
    此外,对于任意非零aa(如aa=-1),aqa\vec{q}q\vec{q}表示同一个旋转,证明见上文链接。
    两个四元数q1\vec{q1}q2\vec{q2}的乘积也表示一个旋转。例如,q1q2\vec{q1}\vec{q2} 表示施加旋转 q2\vec{q2},再施加旋转q1\vec{q1} 。因为:
    q1(q2Pq21)=(q1q2)P(q1q2)1\vec{q1}(\vec{q2}\vec{P}\vec{q2}^{-1})=(\vec{q1}\vec{q2})\vec{P}(\vec{q1}\vec{q2})^{-1}
    总之,通过一个四元数 q\vec{q} 对一个三维点 P\vec{P}(把 P\vec{P} 当成一个实部为0的四元数)施加旋转变换,只需要做如下计算:
    P=qPq1\vec{P'}=\vec{q}\vec{P}\vec{q}^{-1}

    四元数到4*4矩阵

    对于单位四元数q\vec{q},即满足w2+x2+y2+z2=1w^2+x^2+y^2+z^2=1,其3×3旋转矩阵为:
    [12y22z22xy2wz2xz+2wy2xy+2wz12x22z22yz2wx2xz2wy2yz+2wx12x22y2]\begin{bmatrix} 1-2y^2-2z^2&2xy-2wz&2xz+2wy\\ 2xy+2wz&1-2x^2-2z^2&2yz-2wx\\ 2xz-2wy&2yz+2wx&1-2x^2-2y^2 \end{bmatrix}
    加上上文提到的,与三维空间中的平移相复合(先旋转 后平移),则4×4变换矩阵为:
    [12y22z22xy2wz2xz+2wyΔx2xy+2wz12x22z22yz2wxΔy2xz2wy2yz+2wx12x22y2Δz0001]\begin{bmatrix} 1-2y^2-2z^2&2xy-2wz&2xz+2wy&Δx\\ 2xy+2wz&1-2x^2-2z^2&2yz-2wx&Δy\\ 2xz-2wy&2yz+2wx&1-2x^2-2y^2&Δz\\ 0&0&0&1 \end{bmatrix}

    齐次坐标与4*4矩阵的c++实现

    构造了齐次坐标类Coordinate,4*4变换矩阵类Matrix。其中,求逆矩阵的方法为伴随矩阵求逆矩阵。矩阵求逆的验算可以使用这个在线平台云算网人算不如云算。下文代码已经测试通过。

    //Main.cpp
    #include "Matrix.h"
    
    int main()
    {
    	double v1[16] = { 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53 };
    	Matrix m1, m2, m3;
    	m1.SetValue(v1);
    	if (m1.GetDeterminant() == 0)	//计算矩阵行列式,从而验证矩阵可逆
    		return 1;
    	m2 = m1.GetInverse();		//m2为逆矩阵
    	m3 = m1.GetMultiply(m2);	//m3为单位阵
    	return 0;
    }
    
    #pragma once
    //Coordinate.h
    //齐次坐标类
    //w=0,则表示向量(x,y,z)
    //w!=0,则表示点(x/w,y/w,z/w)。w一般取1
    
    #include <math.h>
    
    class Coordinate
    {
    public:
    	double x;
    	double y;
    	double z;
    	double w;
    
    	Coordinate();
    	Coordinate(double x, double y, double z, double w);
    	~Coordinate();
    	void Normalize();	//将点的w设为1 对向量不作变换
    	double GetDotProduct(Coordinate c);	//向量点乘
    	Coordinate GetCrossProduct(Coordinate c);	//向量叉乘
    
    private:
    };
    
    //Coordinate.cpp
    #include "Coordinate.h"
    Coordinate::Coordinate()
    {
    	this->x = 0;
    	this->y = 0;
    	this->z = 0;
    	this->w = 0;
    }
    
    Coordinate::Coordinate(double x, double y, double z, double w)
    {
    	this->x = x;
    	this->y = y;
    	this->z = z;
    	this->w = w;
    }
    
    void Coordinate::Normalize()
    {
    	if (this->w == 0)
    		return;
    	this->x /= this->w;
    	this->y /= this->w;
    	this->z /= this->w;
    	this->w = 1;
    	return;
    }
    
    Coordinate::~Coordinate()
    {}
    
    double Coordinate::GetDotProduct(Coordinate c)
    {
    	double result;
    	result = this->x*c.x + this->y*c.y + this->z*c.z;
    	return result;
    }
    
    Coordinate Coordinate::GetCrossProduct(Coordinate c)
    {
    	Coordinate result;
    	result.x = this->y*c.z - this->z*c.y;
    	result.y = this->z*c.x - this->x*c.z;
    	result.z = this->x*c.y - this->y*c.x;
    	result.w = 0;
    	return result;
    }
    
    #pragma once
    //matrix.h
    //矩阵运算类,以4×4矩阵形式表示空间变换
    //旋转、平移运算的复合,先旋转、后平移
    //对4维齐次坐标进行运算
    
    //#include "Point3D.h"
    #include "Coordinate.h"
    
    class Matrix
    {
    public:
    	Matrix();
    	Matrix(double m[16]);	//矩阵初始化(先行后列)
    	Matrix(Coordinate c0, Coordinate c1, Coordinate c2, Coordinate c3);	//四个列向量构造一个矩阵
    	void SetValue(double m[16]);	//设置矩阵值(先行后列)
    	void SetValue(Coordinate c0, Coordinate c1, Coordinate c2, Coordinate c3);//四个列向量为矩阵赋值
    	~Matrix();
    	Coordinate GetMultiply(Coordinate c);	//this矩阵×齐次坐标
    	Matrix GetMultiply(Matrix m);	//this矩阵×矩阵
    	Matrix GetInverse();	//求逆矩阵
    	double GetDeterminant();	//求this矩阵行列式
    	Matrix GetTranspose();		//求this矩阵的转置矩阵
    private:
    	double m_dItem[4][4];
    	double GetMinor(int y, int x);	//求this矩阵在y,x处的余子式
    	double GetCofactor(int y, int x);	//求this矩阵在y,x处的代数余子式
    };
    
    
    //matrix.cpp
    #include "Matrix.h"
    Matrix::Matrix()
    {
    	int y, x, i = 0;
    	for (y = 0; y < 4; y++)
    	{
    		for (x = 0; x < 4; x++)
    		{
    			m_dItem[y][x] = 0;
    		}
    	}
    }
    
    Matrix::Matrix(double m[16])
    {
    	int y, x, i = 0;
    	for (y = 0; y < 4; y++)
    	{
    		for (x = 0; x < 4; x++)
    		{
    			m_dItem[y][x] = m[i];
    		}
    	}
    }
    
    Matrix::Matrix(Coordinate c0, Coordinate c1, Coordinate c2, Coordinate c3)
    {
    	m_dItem[0][0] = c0.x;
    	m_dItem[0][1] = c1.x;
    	m_dItem[0][2] = c2.x;
    	m_dItem[0][3] = c3.x;
    	m_dItem[1][0] = c0.y;
    	m_dItem[1][1] = c1.y;
    	m_dItem[1][2] = c2.y;
    	m_dItem[1][3] = c3.y;
    	m_dItem[2][0] = c0.z;
    	m_dItem[2][1] = c1.z;
    	m_dItem[2][2] = c2.z;
    	m_dItem[2][3] = c3.z;
    	m_dItem[3][0] = c0.w;
    	m_dItem[3][1] = c1.w;
    	m_dItem[3][2] = c2.w;
    	m_dItem[3][3] = c3.w;
    	return;
    }
    
    Matrix::~Matrix()
    {}
    
    void Matrix::SetValue(double m[16])
    {
    	int y, x, i = 0;
    	for (y = 0; y < 4; y++)
    	{
    		for (x = 0; x < 4; x++)
    		{
    			m_dItem[y][x] = m[i];
    			i++;
    		}
    	}
    	return;
    }
    
    void Matrix::SetValue(Coordinate c0, Coordinate c1, Coordinate c2, Coordinate c3)
    {
    	m_dItem[0][0] = c0.x;
    	m_dItem[0][1] = c1.x;
    	m_dItem[0][2] = c2.x;
    	m_dItem[0][3] = c3.x;
    	m_dItem[1][0] = c0.y;
    	m_dItem[1][1] = c1.y;
    	m_dItem[1][2] = c2.y;
    	m_dItem[1][3] = c3.y;
    	m_dItem[2][0] = c0.z;
    	m_dItem[2][1] = c1.z;
    	m_dItem[2][2] = c2.z;
    	m_dItem[2][3] = c3.z;
    	m_dItem[3][0] = c0.w;
    	m_dItem[3][1] = c1.w;
    	m_dItem[3][2] = c2.w;
    	m_dItem[3][3] = c3.w;
    	return;
    }
    
    Coordinate Matrix::GetMultiply(Coordinate c)
    {
    	Coordinate result;
    	result.x = m_dItem[0][0] * c.x + m_dItem[0][1] * c.y + m_dItem[0][2] * c.z + m_dItem[0][3] * c.w;
    	result.y = m_dItem[1][0] * c.x + m_dItem[1][1] * c.y + m_dItem[1][2] * c.z + m_dItem[1][3] * c.w;
    	result.z = m_dItem[2][0] * c.x + m_dItem[2][1] * c.y + m_dItem[2][2] * c.z + m_dItem[2][3] * c.w;
    	result.w = m_dItem[3][0] * c.x + m_dItem[3][1] * c.y + m_dItem[3][2] * c.z + m_dItem[3][3] * c.w;
    	return result;
    }
    
    Matrix Matrix::GetMultiply(Matrix m)
    {
    	int y, x;
    	Matrix result;
    	for (y = 0; y < 4; y++)
    	{
    		for (x = 0; x < 4; x++)
    		{
    			result.m_dItem[y][x] = this->m_dItem[y][0] * m.m_dItem[0][x] + this->m_dItem[y][1] * m.m_dItem[1][x]
    				+ this->m_dItem[y][2] * m.m_dItem[2][x] + this->m_dItem[y][3] * m.m_dItem[3][x];
    		}
    	}
    	return result;
    }
    
    Matrix Matrix::GetInverse()
    {
    	int y, x;
    	double det;	//矩阵行列式
    	Matrix result;
    
    	//求矩阵行列式
    	det = this->GetDeterminant();
    	if (det == 0)
    		return result;
    	//求每个位置的代数余子式
    	for (y = 0; y < 4; y++)
    	{
    		for (x = 0; x < 4; x++)
    		{
    			result.m_dItem[y][x] = this->GetCofactor(y, x);
    		}
    	}
    	//求伴随矩阵
    	result = result.GetTranspose();
    	//最终结果
    	for (y = 0; y < 4; y++)
    	{
    		for (x = 0; x < 4; x++)
    		{
    			result.m_dItem[y][x] /= det;
    		}
    	}
    
    	return result;
    }
    
    double Matrix::GetDeterminant()
    {
    	double result;
    	result = m_dItem[0][0] * GetCofactor(0, 0) + m_dItem[0][1] * GetCofactor(0, 1) + m_dItem[0][2] * GetCofactor(0, 2) + m_dItem[0][3] * GetCofactor(0, 3);
    	return result;
    }
    
    Matrix Matrix::GetTranspose()
    {
    	int y, x;
    	Matrix result;
    	for (y = 0; y < 4; y++)
    	{
    		for (x = 0; x < 4; x++)
    		{
    			result.m_dItem[y][x] = m_dItem[x][y];
    		}
    	}
    	return result;
    }
    
    double Matrix::GetMinor(int y, int x)
    {
    	int i, n, col[3], row[3];	//col[3]记录行列式对应哪几列,row[3]记录行列式对应的哪几行
    	double result;
    	for (i = 0, n = 0; i < 4; i++)
    	{
    		if (i == x)
    			continue;
    		col[n++] = i;
    	}
    	for (i = 0, n = 0; i < 4; i++)
    	{
    		if (i == y)
    			continue;
    		row[n++] = i;
    	}
    	result = m_dItem[row[0]][col[0]] * (m_dItem[row[1]][col[1]] * m_dItem[row[2]][col[2]] - m_dItem[row[1]][col[2]] * m_dItem[row[2]][col[1]])
    		- m_dItem[row[0]][col[1]] * (m_dItem[row[1]][col[0]] * m_dItem[row[2]][col[2]] - m_dItem[row[1]][col[2]] * m_dItem[row[2]][col[0]])
    		+ m_dItem[row[0]][col[2]] * (m_dItem[row[1]][col[0]] * m_dItem[row[2]][col[1]] - m_dItem[row[1]][col[1]] * m_dItem[row[2]][col[0]]);
    	return result;
    }
    
    double Matrix::GetCofactor(int y, int x)
    {
    	double result;
    	result = pow(-1, y + x)*GetMinor(y, x);
    	return result;
    }
    
    展开全文
  • 本人正在写矩阵史诗级玩法系列博客,到求二元二次方程组的地方来了,消元后最高会生成一元四次方程,而这个求根公式虽然成熟,但代码量也不少,所以单独封装工具类。 本不打算讲解的,但考虑到有的朋友可能没...

    本人正在写矩阵史诗级玩法系列博客,写到求二元二次方程组的地方来了,消元后最高会生成一元四次方程,而这个求根公式虽然成熟,但代码量也不少,所以单独封装成工具类。

    本不打算讲解的,但考虑到有的朋友可能没接触过复数,或者说虽然接触过复数但已经忘得一干二净,那这里我就简单说一下好了。在实数范围内,负数是没办法开平方的,而且对于一些简单的曲线求交(二次或以下)问题来说,出现要对负数开平方的话就意味着没有交点。然而在一些复杂的方程求解中,负数开平方也许是一个重要的中间过程,走完中间过程之后可能会得到实数根,所以数学家们定义了一个新的数i,名为虚数单位,并规定i^2=-1,同时可以使其参与到跟实数的四则运算中且交换律结合律等仍然成立。然后,实数1+实数2*i就构成了复数a+bi。

    四次方程求解经常用到复数,其结构为实数部分一个系数(实部),虚数部分一个系数(虚部),代码如下。

    function ComplexNum(real, image)
    {
    	this.real = isNaN(real) ? 0 : real;
    	this.image = isNaN(image) ? 0 : image;
    }

    复数本身有四则运算,所以完整的代码我把这些运算的实现都写进去了,加减最好理解,乘法稍有难度,除法和开方需要套路,如果觉得看不懂,那可以自己百度或者查阅相关的高中数学教材来补补这方面的知识。

    ComplexNum.js

    function ComplexNum(real, image)
    {
    	this.real = isNaN(real) ? 0 : real;
    	this.image = isNaN(image) ? 0 : image;
    	
    	/**
    	 * 设置复数的值 
    	 * @param reala 复数的实部
    	 * @param imagea 复数的虚部
    	 * 
    	 */
    	function setTo(reala, imagea)
    	{
    		this.real = reala;
    		this.image = imagea;
    	}
    	this.setTo = setTo;
    	
    	/**
    	 * 复数相加 
    	 * @param complex 要与其相加的复数
    	 * @return 
    	 * 
    	 */
    	function add(complex)
    	{
    		return new ComplexNum(this.real + complex.real, this.image + complex.image);
    	}
    	this.add = add;
    	
    	/**
    	 * 为了使用上方便一点,此处加上与实数相加的方法 
    	 * @param num 要与其相加的数字
    	 * @return 
    	 * 
    	 */
    	function addNumber(num)
    	{
    		return new ComplexNum(this.real + num, this.image);
    	}
    	this.addNumber = addNumber;
    	
    	/**
    	 * 复数相减
    	 * @param complex 要与其相减的复数
    	 * @return 
    	 * 
    	 */
    	function subtract(complex)
    	{
    		return new ComplexNum(this.real - complex.real, this.image - complex.image);
    	}
    	this.subtract = subtract;
    	
    	/**
    	 * 为了使用上方便一点,此处加上与实数相减的方法 
    	 * @param num 要与其相减的数字
    	 * @return 
    	 * 
    	 */
    	function subtractNumber(num)
    	{
    		return new ComplexNum(this.real - num, image);
    	}
    	this.subtractNumber = subtractNumber;
    	
    	/**
    	 * 复数乘法 (运算法则是利用多项式乘法进行展开得到)
    	 * @param complexNum 要与其相乘的复数
    	 * @return 
    	 * 
    	 */
    	function multiply(complexNum)
    	{
    		return new ComplexNum(this.real * complexNum.real - this.image * complexNum.image, this.image * complexNum.real + this.real * complexNum.image);
    	}
    	this.multiply = multiply;
    	
    	/**
    	 * 为了使用上方便一点,此处加上与实数相乘的方法 
    	 * @param num 要与其相乘的数字
    	 * @return 
    	 * 
    	 */
    	function multiplyNumber(num)
    	{
    		return new ComplexNum(this.real * num, this.image * num);
    	}
    	this.multiplyNumber = multiplyNumber;
    	
    	/**
    	 * 复数除法 (运算法则是通过平方差公式,分子分母同时乘以分母的共轭复数以去除分母中的虚部,然后就利用乘法法则进行计算)
    	 * @param complexNum 要与其相除的复数
    	 * @return 
    	 * 
    	 */
    	function divide(n)
    	{
    		//分母化为实数
    		var denominator = n.real * n.real + n.image * n.image;
    		//分子也乘以同样的复数,并除以分母即得最终结果
    		return new ComplexNum((this.real * n.real + this.image * n.image) / denominator, (this.image * n.real - this.real * n.image) / denominator);
    	}
    	this.divide = divide;
    	
    	/**
    	 * 为了使用上方便一点,此处加上与实数相除的方法 
    	 * @param num 要与其相除的数字
    	 * @return 
    	 * 
    	 */
    	function divideNumber(num)
    	{
    		return new ComplexNum(this.real / num, this.image / num);
    	}
    	this.divideNumber = divideNumber;
    	
    	/**
    	 * 开平方运算
    	 * @return 
    	 * 
    	 */
    	function squareRoot()
    	{			
    		return this.getRoot(2);
    	}
    	this.squareRoot = squareRoot;
    	
    	/**
    	 * 开立方运算 
    	 * @return 
    	 * 
    	 */
    	function cubicRoot()
    	{
    		return this.getRoot(3);
    	}
    	this.cubicRoot = cubicRoot;
    	
    	/**
    	 * 开任意整数次方的运算 
    	 * @param times
    	 * @return 
    	 * 
    	 */
    	function getRoot(times)
    	{
    		var vec = [];			
    		//复数开方运算的原理是把辐角根据次数进行平分
    		var degree = this.degree;
    		degree /= times;
    		//然后多个方根平分360度,所以需要算出每个方根之间的辐角间隔
    		var degreeUnit = 360 / times;
    		//复数长度(模)直接开方即可
    		var lengthRoot = Math.pow(this.length, 1 / times);
    		var cosDic = AngleUtil.getCosDic();
    		var sinDic = AngleUtil.getSinDic();
    		//然后就能通过循环生成所有开方结果
    		for(var i = 0; i < times; i ++)
    		{
    			var currentDegree = (degree + i * degreeUnit);
    			var currentAngle = currentDegree * Math.PI / 180;
    			var cos = isNaN(cosDic[currentDegree]) ? Math.cos(currentAngle) : cosDic[currentDegree];
    			var sin = isNaN(sinDic[currentDegree]) ? Math.sin(currentAngle) : sinDic[currentDegree];
    			//trace(lengthRoot * cos, lengthRoot * sin);
    			vec.push(new ComplexNum(lengthRoot * cos, lengthRoot * sin));
    		}
    		return vec;
    	}
    	this.getRoot = getRoot;
    	
    	/**
    	 * 复数的辐角主值(复数所在点与坐标连线跟水平线的夹角),以弧度为单位
    	 * 必要时可用degree属性可以更有效避免边缘位置的浮点误差引发的错误
    	 * @see degree()
    	 * 
    	 */	
    	Object.defineProperty(this, "angle", {get: getAngle});
    	function getAngle()
    	{
    		//由于复数开方基于角度,所以一旦有浮点误差就会导致角度在边缘位置出现突跃导致严重错误,所以遇到浮点误差的话,我会强制将角度设置为0
    		if(Math.abs(this.image) < 0.0000001)
    		{
    			return this.real > 0 ? 0 : Math.PI; 
    		}else if(Math.abs(this.real) < 0.0000001)
    		{
    			return this.image > 0 ? Math.PI * 0.5 : (this.image == 0 ? 0 : - Math.PI * 0.5);
    		}else
    		{
    			return Math.atan2(this.image, this.real);
    		}
    	}
    
    	
    	/**
    	 * 复数的辐角主值,以角度值表示(跟弧度相比,该方法能更有效地避免边缘位置的浮点误差引发的错误)
    	 * 
    	 */	
    	Object.defineProperty(this, "degree", {get: getDegree});	 
    	function getDegree()
    	{
    		//由于复数开方基于角度,所以一旦有浮点误差就会导致角度在边缘位置出现突跃导致严重错误,所以遇到浮点误差的话,我会强制将角度设置为0
    		if(Math.abs(this.image) < 0.0000001)
    		{
    			return this.real > 0 ? 0 : 180; 
    		}else if(Math.abs(this.real) < 0.0000001)
    		{
    			return this.image > 0 ? 90 : (this.image == 0 ? 0 : 270);
    		}else
    		{
    			return Math.atan2(this.image, this.real) / Math.PI * 180;
    		}
    	}
    	
    	/**
    	 * 复数的模(长度) 
    	 * @return 
    	 * 
    	 */
    	Object.defineProperty(this, "length", {get: getLength});
    	function getLength()
    	{
    		return Math.sqrt(this.real * this.real + this.image * this.image);
    	}
    	
    	/**
    	 * 返回当前复数的一个副本 
    	 * @return 
    	 * 
    	 */
    	function clone()
    	{
    		return new ComplexNum(this.real, this.image);
    	}
    	this.clone = clone;
    	
    	function toString()
    	{
    		var realStr = String((this.real != 0 || this.image == 0) ? real : "");
    		var imageStr = (this.image == 0) ? "" : ((this.image < 0 ? ("-" + (-this.image)) : ((realStr == "" ? "" : "+") + this.image)) + "i");
    		return realStr + imageStr;
    	}
    	this.toString = toString;
    }

    复数乘法跟三角函数密切相关,而且60度倍数的三角函数出现频率特别高,所以我又定义了一些常量,以防直接计算累积不必要的浮点误差。

    ComplexConsts.js

    function ComplexConsts()
    {
    	
    }
    
    /**
     * OMEGA是模为1,幅角主值等于120度的复数,它是1开三次方的结果,在解3次和4次方程中非常常用 
     * OMEGA就是希腊字母里最像w的那个
     * 
     */
    ComplexConsts.OMEGA = new ComplexNum(1 / 2, Math.sqrt(3) / 2);
    
    /**
     * 理论上OMEGA的平方可以用两个OMEGA相乘得到,但由于容易产生浮点误差,加上数值固定,因此也直接做成常量
     *  
     */
    ComplexConsts.OMEGA_SQUARE = new ComplexNum(1 / 2, Math.sqrt(3) / 2);		
    
    /**
     * OMEGA的3次方恰好等于实数1,就最好不要再自己用三个OMEGA来相乘了
     *  
     */
    ComplexConsts.OMEGA_CUBIC = new ComplexNum(1, 0);
    
    /**
     * OMEGA的0次方,纯属为了让代码清晰而定义的常量
     *  
     */
    ComplexConsts.OMEGA_ZERO = new ComplexNum(1, 0);
    
    /**
     * 虚数单位i
     *  
     */
    ComplexConsts.I = new ComplexNum(0, 1);

    AngleUtil.js

    function AngleUtil()
    {
    	
    }
    
    AngleUtil.getCosDic = function()
    {
    	if(AngleUtil._cosDic == undefined)
    	{
    		AngleUtil._cosDic = [];
    		AngleUtil._cosDic[60] = AngleUtil._cosDic[-60] = AngleUtil._cosDic[300] = AngleUtil._cosDic[-300] = 0.5;
    		AngleUtil._cosDic[120] = AngleUtil._cosDic[-120] = AngleUtil._cosDic[240] = AngleUtil._cosDic[-240] = -0.5;
    		AngleUtil._cosDic[0] = AngleUtil._cosDic[360] = 1;
    		AngleUtil._cosDic[180] = AngleUtil._cosDic[-180] = -1;
    		AngleUtil._cosDic[90] = AngleUtil._cosDic[270] = AngleUtil._cosDic[-90] = AngleUtil._cosDic[-270] = 0;	
    	}
    	return AngleUtil._cosDic;
    }
    
    AngleUtil.getSinDic = function()
    {
    	if(AngleUtil._sinDic == undefined)
    	{
    		AngleUtil._sinDic = [];
    		AngleUtil._sinDic[30] = AngleUtil._sinDic[150] = AngleUtil._sinDic[-330] = AngleUtil._sinDic[-210] = 0.5;
    		AngleUtil._sinDic[-30] = AngleUtil._sinDic[-150] = AngleUtil._sinDic[210] = AngleUtil._sinDic[330] = -0.5;
    		AngleUtil._sinDic[90] = AngleUtil._sinDic[-270] = 1;
    		
    		AngleUtil._sinDic[270] = AngleUtil._sinDic[-90] = -1;
    		AngleUtil._sinDic[180] = AngleUtil._sinDic[-180] = AngleUtil._sinDic[0] = AngleUtil._sinDic[360] = 0;
    	}
    	return AngleUtil._sinDic;
    }

    真没想到,弄完这些辅助类就把文章撑那么长了。那我就分开两篇写好了。

    其实我可以弄附件,但有些东西没测好,附件又似乎不太好改,那就还是直接贴吧。

    下篇我贴出解方程的核心类。

    展开全文
  • 默认读者学过线性代数的基础知识。1. 多元线性方程组的形式多元线性...如果取 以及 多元线性方程组可以写成 ,这里不再把矩阵和向量写成粗体。如果把 的列向量分别用 表示,即 ,多元线性方程组还可以写成 。2. 多元...
  • n元向量可以写成行向量或列向量的形式,二者相差一次转置运算,记为aT≠aa^T \neq aaT​=a 所有n元实向量的集合记作RnR^nRn 一般地,对所有没有指明的向量,都当作列向量,使用ei∈Rne_i \in R^nei​∈Rn表示第i个...
  • 2. rotation-scaling matrix假如,为实数,且不同时为0,则将下面的矩阵称为rotation-scaling matrix,则有,A可以写成下面的旋转+缩放形式,其中,,则先旋转,再倍乘。 2. 的特征值为。3. 矩阵的复特征...
  • exp() %不能写成e^x exp(1) %不能写成e 取整函数 round %四舍五入取整 fix %朝0方向取整 floor %朝-∞方向取整 ceil %朝+∞方向取整 取余函数 mod(-13,5) %结果为3 rem(-13,5) %结果为-2 复数 由于 i
  • 定义 用 表示四元数是为了纪念其发明者 Hamilton.其中: 可以根据 来推导以下式子: 跟复数类似,我们可以把四元数写成: 它的基... : 类似的,我们也可以把它写成矩阵形式: 这个矩阵其实也很类似复数的矩阵:除了...
  • 定义用 表示四元数是为了纪念其发明者 Hamilton.其中:可以根据 来推导以下式子:跟复数类似,我们可以把... :类似的,我们也可以把它写成矩阵形式:这个矩阵其实也很类似复数的矩阵:除了对角线上的元素 , 差一点...
  • 四元组 这篇文章内容将比较偏数学,为方便快速复习,这里只列出关键的结论。...乘法可以写成矩阵形式 注意因为涉及叉乘,左手系和右手系里的四元组不一样。 乘法和矩阵乘法一样,有结合律没有交换律。 ...
  • 默认读者学过线性代数的基础知识。1. 多元线性方程组的形式多元线性...如果取 以及 多元线性方程组可以写成 ,这里不再把矩阵和向量写成粗体。如果把 的列向量分别用 表示,即 ,多元线性方程组还可以写成 。2. 多元...
  • (11)向量组及其线性组合

    千次阅读 2016-12-04 14:52:26
    定义1:n个有次序的数 a1,a2,....an所组成的数组称为n维向量,这n...n维向量写成一行,称为行向量,也就是行矩阵,如: n维向量写成一列,称为列向量,也就是列矩阵,如: 注意: 1.行向量和列向量都按照矩阵
  • 3.出二次型 的矩阵,并将这个二次型化为一个与它等价的二次型,使后者只含变量的平方项. 4.令A是数域F上一个n阶斜对称矩阵,即满足条件 . (i)A必与如下形式的一个矩阵合同: (ii) 斜对称矩阵的秩一定是偶数...
  • 第三讲第四节-四元数

    2020-10-09 16:08:43
    在二维平面上,我们想要将复平面的向量旋转θ\thetaθ角时候,我们可以将复向量乘以单位长度复数eiθ{e^{i\theta }}eiθ,而eiθ{e^{i\theta }}eiθ可以写成复数形式: eiθ=cos⁡θ+isin⁡θ{e^{i\theta }} = \cos ...
  • 19 个字符 , 标识符中第一个字符必须是英文 字母MATLAB区分大小 默认状态下 A 和 a 被认为是两个不同的字符 case sensitive 一数组和矩阵 ( 一数组的赋值 数组是指一组实数或复数的长方阵列 它可以是一维的行...
  • 变量和常量的标识符最长允许 19 个字符 , 标识符中第一个字符必须是英文字母MATLAB区分大小 默认状态下 A 和 a 被认为是两个不同的字符 case sensitive 一数组和矩阵 ( 一数组的赋值 数组是指一组实数或复数的...
  • 19 个字符 , 标识符中第一个字符必须是英文 字母MATLAB区分大小 默认状态下 A 和 a 被认为是两个不同的字符 case sensitive 一数组和矩阵 ( 一数组的赋值 数组是指一组实数或复数的长方阵列 它可以是一维的行...
  • 四元数相关学习理解

    2019-11-26 15:55:12
    四元数(Quaternions)是由爱尔兰数学家汉密尔顿(William Rowan Hamilton,1805~1865)在1843年提出来的数学概念,它将复数所描述的三维空间拓展到四维...四元数的形式可以写成式: 并且 方向余弦矩阵DCM(用四...
  • 这里的λ就是你刚才解出来的特征根,整个意思是要你写成r(t)=c1e^λ1t+c2eλt的形式,那个c1,c2求法如上,等号右侧关于λ的矩阵是一个范德蒙矩阵的逆矩阵,乘以一个关于初始值的向量——而这两者都是已知的
  • Jin Li大佬整理的python笔记,鄙人学习后添加了许多自己的见解,于是最后写成了这系列手册。 本文代码均在jupyter notebook上实现。 文章目录数组类型复数数组制定数组类型常用方法将输入值设置为有步长的列表返回...
  • (casesensitive)一、数组和矩阵(一)数组的赋值数组是指一组实数或复数的长方阵列。它可以是一维的“行”或“列”,可以是二维的“矩形”,也可以是三维的甚至更高的维数。在MATLAB中的变量和常量都代表数组,...
  • 四元数乘法计算

    千次阅读 2020-09-10 22:52:09
    其中复数式、矢量式和三角式基本是一回事,都是把四元数写成一个标量和一个向量的和的形式。指数式和矩阵式就是一种表示方法,涉及到数学意义和运算还是主要用前三种。 下面介绍不同四元数表示形式的乘法: 1.复数...
  • 我们来定义一个四元数:我们可以把它写成,其中,。那么是矢量,表示三维空间中的旋转轴。w是标量,表示旋转角度。那么就是绕轴旋转w度,所以一个四元数可以表示一个完整的旋转。只有单位四元数才可以表示旋转,至于...
  • 5.5.7 SEARCHB——以字节为单位不区分大小地查找指定字符的位置 191 5.5.8 SUBSTITUTE——以指定文本进行替换 191 5.6 删除文本中的字符 192 5.6.1 CLEAN——删除无法打印的字符 192 5.6.2 TRIM——删除多余...
  • 【习2.2】 习2-6 如果在遍历单链表时,将p=p.next语句写成p.next=p,结果会怎样? 5 【习2.3】 实验2.2 由指定数组中的多个对象构造单链表。 5 【习2.4】 实验2.2 单链表的查找、包含、删除操作详见8.2.1。 5 【习...
  • python cookbook(第3版)

    2016-01-06 22:24:38
    3.10 矩阵与线性代数运算 3.11 随机选择 3.12 基本的日期与时间转换 3.13 计算最后一个周五的日期 3.14 计算当前月份的日期范围 3.15 字符串转换为日期 3.16 结合时区的日期操作 第四章:迭代器与生成器 ...
  • 《你必须知道的495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    5.6 如果NULL定义#define NULL((char *)0) ,不就可以向函数传入不加转换的NULL 了吗? 57 5.7 我的编译器提供的头文件中定义的NULL为0L。为什么? 57 5.8 NULL可以合法地用作函数指针吗? 57 5.9 如果NULL...

空空如也

空空如也

1 2 3
收藏数 56
精华内容 22
关键字:

复数写成矩阵