MQL5 中的矩阵和向量
有序数据的集合,其中所有元素的类型相同,通常会经由数组进行操作,其内每个元素都可以通过按照其索引进行访问。 数组广泛用于解决各种线性代数问题、数学建模任务、机器学习、等等。 一般来说,这类问题的解决方案是基于矩阵和向量的数学运算,运用这些矩阵和向量,可以将非常复杂的变换改写成紧凑、简单的方程形式。 此类运算的程序化实现需要优良的数学知识,以及编写复杂嵌套循环的能力。 针对这样的程序进行调试和修复故障可能具有相当的挑战性。
运用特殊的数据类型“矩阵”和“向量”,可以创建非常贴合数学符号本意的代码,同时避免创建嵌套循环,或在计算中分心记忆数组的正确索引。 在本文中,我们将了解如何在 MQL5 中创建、初始化和运用矩阵和向量对象。
“向量(vector)”类型
向量(vector)是一个一维的双精度型(double)数组。 针对向量定义了以下运算:加法和乘法,以及获取向量长度或模(module)的范数(Norm)。 在程序化过程中,向量通常由同质元素的数组来表示,针对这些不能定义非规则向量运算,即数组不能相加或相乘,并且它们没有范数。
在数学中,向量可以表示为行向量,即由一行和 n 列组成的数组,以及字符串向量,即由一列和 n 行组成的矩阵。 在 MQL5 中,“vector(向量)”类型没有行和列子类型,因此程序员必须了解特定运算中所用的是哪种向量类型。
使用以下内置方法创建和初始化向量。
方法 | NumPy 类比 | 说明 |
---|---|---|
void vector.Init( ulong size); | 创建指定长度的向量,其中的值未定义 | |
static vector vector::Ones(ulong size); | ones | 创建指定长度的向量,用一填充 |
static vector vector::Zeros(ulong size); | zeros | 创建指定长度的向量,用零填充 |
static vector vector::Full(ulong size,double value); | full | 创建指定长度的向量,并用指定值填充 |
operator = | 返回向量的副本 | |
void vector.Resize(const vector v); | 往结尾添加新值来调整向量大小 |
矢量创建示例:
void OnStart() { //--- vector initialization examples vector v; v.Init(7); Print("v = ", v); vector v1=vector::Ones(5); Print("v1 = ", v1); vector v2=vector::Zeros(3); Print("v2 = ", v2); vector v3=vector::Full(6, 2.5); Print("v3 = ", v3); vector v4{1, 2, 3}; Print("v4 = ", v4); v4.Resize(5); Print("after Resize(5) v4 = ", v4); vector v5=v4; Print("v5 = ", v5); v4.Fill(7); Print("v4 = ", v4, " v5 =",v5); } /* Execution result v = [4,5,6,8,10,12,12] v1 = [1,1,1,1,1] v2 = [0,0,0] v3 = [2.5,2.5,2.5,2.5,2.5,2.5] v4 = [1,2,3] after Resize(5) v4 = [1,2,3,7,7] v5 = [1,2,3,7,7] v4 = [7,7,7,7,7] v5 =[1,2,3,7,7] */
Init() 方法不仅可用于为向量分配内存,还可依据函数值来初始化向量元素。 在这种情况下,向量大小作为第一个参数传递给 Init,函数名作为第二个参数。 如果函数包含参数,则应在函数名后立即指定这些参数,并用逗号分隔。
函数本身必须包含向量的引用,且作为第一个参数传入。 在 Init 调用期间不应传递向量。 我们以 Arange 函数为例来查看方法的运算。 此函数模仿 numpy.arange。
void OnStart() { //--- vector v; v.Init(7,Arange,10,0,0.5); // 3 parameters are passed with Arange call Print("v = ", v); Print("v.size = ",v.Size()); } //+------------------------------------------------------------------+ //| Values are generated within the half-open interval [start, stop)| //+------------------------------------------------------------------+ void Arange(vector& v, double stop, double start = 0, double step = 1) // the function has 4 parameters { if(start >= stop) { PrintFormat("%s wrong parameters! start=%G stop=%G", __FILE__,start, stop); return; } //--- int size = (int)((stop - start) / step); v.Resize(size); double value = start; for(ulong i = 0; i < v.Size(); i++) { v[i] = value; value += step; } } /* Execution result v = [0,0.5,1,1.5,2,2.5,3,3.5,4,4.5,5,5.5,6,6.5,7,7.5,8,8.5,9,9.5] v.size = 20 */
Arange 函数有两个可选参数,“start” 和 “stop”。 因此,Init(7,Arange,10) 的另一个可能调用和相关结果如下:
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- vector v; v.Init(7,Arange,10); Print("v = ", v); Print("v.size = ",v.Size()); } ... /* v = [0,1,2,3,4,5,6,7,8,9] v.size = 10 */
向量运算
通常可以在向量上执行使用标量的加、减、乘、除运算。
//+------------------------------------------------------------------+ //| vector2_article.mq5 | //| Copyright 2021, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- vector v= {1, 2, 3, 4, 5}; Print("Examples without saving vector changes"); Print("v = ", v); Print("v+5 = ", v+5); Print("v-Pi= ", v-M_PI); Print("v*2.0= ", v*2); Print("v/3.0= ", v/3.0); Print("Save all vector changes"); Print("v = ", v); Print("v+5 = ", v=v+5); Print("v-Pi= ", v=v-M_PI); Print("v*2.0= ", v= v*2); Print("v/3.0= ", v= v/3.0); } /* Execution result Examples without saving vector changes v = [1,2,3,4,5] v+5 = [6,7,8,9,10] v-Pi= [-2.141592653589793,-1.141592653589793,-0.1415926535897931,0.8584073464102069,1.858407346410207] v*2.0= [2,4,6,8,10] v/3.0= [0.3333333333333333,0.6666666666666666,1,1.333333333333333,1.666666666666667] Save all vector changes v = [1,2,3,4,5] v+5 = [6,7,8,9,10] v-Pi= [2.858407346410207,3.858407346410207,4.858407346410207,5.858407346410207,6.858407346410207] v*2.0= [5.716814692820414,7.716814692820414,9.716814692820414,11.71681469282041,13.71681469282041] v/3.0= [1.905604897606805,2.572271564273471,3.238938230940138,3.905604897606805,4.572271564273471] */ //+------------------------------------------------------------------+
向量支持两个大小相同向量的元素加法、减法、乘法和除法运算。
void OnStart() { //--- vector a = {1, 2, 3}; vector b = {2, 4, 6}; Print("a + b = ", a + b); Print("a - b = ", a - b); Print("a * b = ", a * b); Print("b / a = ", b / a); } /* Execution result a + b = [3,6,9] a - b = [-1,-2,-3] a * b = [2,8,18] b / a = [2,2,2] */
为这些数据类型定义了四种运算。
void OnStart() { //--- vector a={1, 2, 3}; vector b={4, 5, 6}; Print("a = ", a); Print("b = ", b); Print("1) a.Dot(b) = ", a.Dot(b)); Print("2) a.MatMul(b) = ", a.MatMul(b)); Print("3) a.Kron(b) = ", a.Kron(b)); Print("4) a.Outer(b) = \n", a.Outer(b)); } /* Execution result a = [1,2,3] b = [4,5,6] 1) a.Dot(b) = 32.0 2) a.MatMul(b) = 32.0 3) a.Kron(b) = [[4,5,6,8,10,12,12,15,18]] 4) a.Outer(b) = [[4,5,6] [8,10,12] [12,15,18]] */
如您从示例中所见,Outer 方法返回一个矩阵,其中行数和列数对应于相乘向量的大小。 Dot 和 MatMul 的操作方式相同。
向量范数
向量和矩阵范数表示向量长度(量级)和绝对值。 计算向量范数的三种可能方法已罗列在 ENUM_VECTOR_NORM 枚举之中。void OnStart() { //--- struct str_vector_norm { ENUM_VECTOR_NORM norm; int value; }; str_vector_norm vector_norm[]= { {VECTOR_NORM_INF, 0}, {VECTOR_NORM_MINUS_INF, 0}, {VECTOR_NORM_P, 0}, {VECTOR_NORM_P, 1}, {VECTOR_NORM_P, 2}, {VECTOR_NORM_P, 3}, {VECTOR_NORM_P, 4}, {VECTOR_NORM_P, 5}, {VECTOR_NORM_P, 6}, {VECTOR_NORM_P, 7}, {VECTOR_NORM_P, -1}, {VECTOR_NORM_P, -2}, {VECTOR_NORM_P, -3}, {VECTOR_NORM_P, -4}, {VECTOR_NORM_P, -5}, {VECTOR_NORM_P, -6}, {VECTOR_NORM_P, -7} }; vector v{1, 2, 3, 4, 5, 6, 7}; double norm; Print("v = ", v); //--- for(int i=0; i<ArraySize(vector_norm); i++) { switch(vector_norm[i].norm) { case VECTOR_NORM_INF : norm=v.Norm(VECTOR_NORM_INF); Print("v.Norm(VECTOR_NORM_INF) = ", norm); break; case VECTOR_NORM_MINUS_INF : norm=v.Norm(VECTOR_NORM_MINUS_INF); Print("v.Norm(VECTOR_NORM_MINUS_INF) = ", norm); break; case VECTOR_NORM_P : norm=v.Norm(VECTOR_NORM_P, vector_norm[i].value); PrintFormat("v.Norm(VECTOR_NORM_P,%d) = %G", vector_norm[i].value, norm); } } } /* v = [1,2,3,4,5,6,7] v.Norm(VECTOR_NORM_INF) = 7.0 v.Norm(VECTOR_NORM_MINUS_INF) = 1.0 v.Norm(VECTOR_NORM_P,0) = 7 v.Norm(VECTOR_NORM_P,1) = 28 v.Norm(VECTOR_NORM_P,2) = 11.8322 v.Norm(VECTOR_NORM_P,3) = 9.22087 v.Norm(VECTOR_NORM_P,4) = 8.2693 v.Norm(VECTOR_NORM_P,5) = 7.80735 v.Norm(VECTOR_NORM_P,6) = 7.5473 v.Norm(VECTOR_NORM_P,7) = 7.38704 v.Norm(VECTOR_NORM_P,-1) = 0.385675 v.Norm(VECTOR_NORM_P,-2) = 0.813305 v.Norm(VECTOR_NORM_P,-3) = 0.942818 v.Norm(VECTOR_NORM_P,-4) = 0.980594 v.Norm(VECTOR_NORM_P,-5) = 0.992789 v.Norm(VECTOR_NORM_P,-6) = 0.99714 v.Norm(VECTOR_NORM_P,-7) = 0.998813 */
利用范数,可以测量两个向量之间的距离:
void OnStart() { //--- vector a{1,2,3}; vector b{2,3,4}; double distance=(b-a).Norm(VECTOR_NORM_P,2); Print("a = ",a); Print("b = ",b); Print("|a-b| = ",distance); } /* Execution result a = [1,2,3] b = [2,3,4] |a-b| = 1.7320508075688772 */
“矩阵(matrix)” 类型
向量是矩阵的特例,它实际上是一个双精度(double)型的二维数组。 故此,矩阵可以被视为大小相同的向量数组。 矩阵的行数对应于向量的数量,而列数等于向量长度。
加法和乘法运算也适用于矩阵。 传统的编程语言使用数组来表示矩阵。 但是,常规数组之间不能相加或相乘,它们也没有范数。数学上考虑了许多不同的矩阵类型。 例如,单位矩阵、对称矩阵、斜对称矩阵、上下三角矩阵、等类型。
与向量方法类似,矩阵也能利用内置方法创建和初始化。
方法 | NumPy 中的类比法 | 说明 |
---|---|---|
void static matrix.Eye(const int rows, const int cols, const int ndiag=0) | 构造一个矩阵,在指定的对角线上填 1,在其它地方填 0 | |
void matrix.Identity() | 在矩阵主对角线上填 1,并在其它地方填 0 | |
void static matrix.Ones(const int rows, const int cols) | 根据行数和列数构造一个新的矩阵,并用 1 填充 | |
void static matrix.Zeros(const int rows, const int cols) | 根据行数和列数构造一个新的矩阵,并用 0 填充 | |
void static matrix.Tri(const int rows, const int cols, const int ndiag=0) | tri | 构造一个矩阵,在指定对角线上填 1,在其下和其它地方填 0 |
void matrix.Diag(const vector v, const int ndiag=0) | diag | 提取对角线或构造对角线矩阵 |
void matrix.Full(const int rows, const int cols, const scalar value) | 根据行数和列数构造一个新矩阵,并用标量值填充 | |
void matrix.Fill(const scalar value) | 用指定的值填充矩阵 |
矩阵构造和填充示例:
void OnStart() { //--- matrix m{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; Print("m = \n", m); matrix ones=matrix::Ones(4, 4); Print("ones = \n", ones); matrix zeros=matrix::Zeros(4, 4); Print("zeros = \n", zeros); matrix eye=matrix::Eye(4, 4); Print("eye = \n", eye); matrix identity(4, 5); Print("matrix_identity\n", identity); identity.Identity(); Print("matrix_identity\n", identity); matrix tri=matrix::Tri(3, 4); Print("tri = \n", tri); Print("tri.Transpose() = \n", tri.Transpose()); // transpose the matrix matrix diag(5, 5); Print("diag = \n", diag); vector d{1, 2, 3, 4, 5}; diag.Diag(d); Print("diag = \n", diag); // insert values from the vector into the matrix diagonal matrix fill(5, 5); fill.Fill(10); Print("fill = \n", fill); matrix full =matrix::Full(5, 5, 100); Print("full = \n", full); matrix init(5, 7); Print("init = \n", init); m.Init(4, 6); Print("init = \n", init); matrix resize=matrix::Full(2, 2, 5); resize.Resize(5,5); Print("resize = \n", resize); } /* Execution result m = [[1,2,3] [4,5,6] [7,8,9]] ones = [[1,1,1,1] [1,1,1,1] [1,1,1,1] [1,1,1,1]] zeros = [[0,0,0,0] [0,0,0,0] [0,0,0,0] [0,0,0,0]] eye = [[1,0,0,0] [0,1,0,0] [0,0,1,0] [0,0,0,1]] matrix_identity [[1,0,0,0,0] [0,1,0,0,0] [0,0,1,0,0] [0,0,0,1,0]] matrix_identity [[1,0,0,0,0] [0,1,0,0,0] [0,0,1,0,0] [0,0,0,1,0]] tri = [[1,0,0,0] [1,1,0,0] [1,1,1,0]] tri.Transpose() = [[1,1,1] [0,1,1] [0,0,1] [0,0,0]] diag = [[0,0,0,0,0] [0,0,0,0,0] [0,0,0,0,0] [0,0,0,0,0] [0,0,0,0,0]] diag = [[1,0,0,0,0] [0,2,0,0,0] [0,0,3,0,0] [0,0,0,4,0] [0,0,0,0,5]] fill = [[10,10,10,10,10] [10,10,10,10,10] [10,10,10,10,10] [10,10,10,10,10] [10,10,10,10,10]] full = [[100,100,100,100,100] [100,100,100,100,100] [100,100,100,100,100] [100,100,100,100,100] [100,100,100,100,100]] resize = [[5,5,0,0,0] [5,5,0,0,0] [0,0,0,0,0] [0,0,0,0,0] [0,0,0,0,0]] */
以下示例展示了如何使用自定义函数填充矩阵:
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- matrix random(4, 5, MatrixRandom); Print("random = \n",random); matrix init(3, 6, MatrixSetValues); Print("init = \n", init); } //+------------------------------------------------------------------+ //| Fills the matrix with random values | //+------------------------------------------------------------------+ void MatrixRandom(matrix& m) { for(ulong r=0; r<m.Rows(); r++) { for(ulong c=0; c<m.Cols(); c++) { m[r][c]=double(MathRand())/32767.; } } } //+------------------------------------------------------------------+ //| Fills the matrix with powers of a number | //+------------------------------------------------------------------+ void MatrixSetValues(matrix& m, double initial=1) { double value=initial; for(ulong r=0; r<m.Rows(); r++) { for(ulong c=0; c<m.Cols(); c++) { m[r][c]=value; value*=2; } } } /* Execution result random = [[0.4200262459181494,0.5014496292001098,0.7520371105075229,0.652058473464156,0.08783227027191992] [0.5991088595233008,0.4311960203863643,0.8718832972197638,0.1350138859218116,0.901882992034669] [0.4964445936460463,0.8354747154148991,0.5258339182714317,0.6055482650227363,0.5952940458388012] [0.3959166234321116,0.8146916104617451,0.2053590502639851,0.2657551805169835,0.3672292245246742]] init = [[1,2,4,8,16,32] [64,128,256,512,1024,2048] [4096,8192,16384,32768,65536,131072]] */
矩阵可以通过两种方式来构造,且无需初始化值:
//--- create a matrix of a given 'rows x cols' size matrix m(3, 3); // ------ equivalent matrix m; m.Resize(3, 3);
矩阵范数
计算矩阵范数的九种可能方法已罗列在 ENUM_MATRIX_NORM 枚举之中。
void OnStart() { //--- ENUM_MATRIX_NORM matrix_norm[]= {MATRIX_NORM_FROBENIUS, MATRIX_NORM_SPECTRAL, MATRIX_NORM_NUCLEAR, MATRIX_NORM_INF, MATRIX_NORM_MINUS_INF, MATRIX_NORM_P1, MATRIX_NORM_MINUS_P1, MATRIX_NORM_P2, MATRIX_NORM_MINUS_P2 }; matrix m{{1,2,3},{4,5,6},{7,8,9}}; Print("matrix m:\n",m); //--- compute the norm using all ways double norm; for(int i=0; i<ArraySize(matrix_norm); i++) { norm=m.Norm(matrix_norm[i]); PrintFormat("%d. Norm(%s) = %.6f",i+1, EnumToString(matrix_norm[i]),norm); } //--- return; } /* Execution result matrix m: [[1,2,3] [4,5,6] [7,8,9]] 1. Norm(MATRIX_NORM_FROBENIUS) = 16.881943 2. Norm(MATRIX_NORM_SPECTRAL) = 14.790157 3. Norm(MATRIX_NORM_NUCLEAR) = 17.916473 4. Norm(MATRIX_NORM_INF) = 24.000000 5. Norm(MATRIX_NORM_MINUS_INF) = 6.000000 6. Norm(MATRIX_NORM_P1) = 18.000000 7. Norm(MATRIX_NORM_MINUS_P1) = 12.000000 8. Norm(MATRIX_NORM_P2) = 16.848103 9. Norm(MATRIX_NORM_MINUS_P2) = 0.000000 */
矩阵和向量运算
矩阵提供了解决数学问题的特殊方法:
- 换位
- 元素级矩阵加法、减法、乘法、除法
- 矩阵元素与标量的加法、减法、乘法和除法
- 矩阵和向量的 MatMul 积(矩阵积)
- Inner()
- Outer()
- Kron()
- Inv() — 矩阵逆转换
- Solve() — 解线性方程组
- LstSq() — 返回线性代数方程组的最小二乘解(对于非平方或退化矩阵)
- PInv() — 伪逆最小二乘矩阵
- 按照列、行和对角线运算
矩阵分解:
方法 | NumPy 中的类比法 | 说明 |
---|---|---|
bool matrix.Cholesky(matrix& L) | cholesky | 计算 Cholesky 分解 |
bool matrix.QR(matrix& Q, matrix& R) | qr | 计算 QR 分解 |
bool matrix.SVD(matrix& U, matrix& V, vector& singular_values) | 计算 SVD 分解 | |
bool matrix.Eig(matrix& eigen_vectors, vector& eigen_values) | 计算方矩阵的特征值和右特征向量 | |
bool matrix.EigVals(vector& eigen_values) | 计算一般矩阵的特征值 | |
bool matrix.LU(matrix& L, matrix& U) |
| 实现矩阵的 LU 分解:低位三角矩阵和上位三角矩阵的乘积 |
bool matrix.LUP(matrix& L, matrix& U, matrix& P) |
| 使用部分旋转实现 LUP 分解,这是一种具有行排列的 LU 分解:PA=LU |
矩阵与向量的乘积
MatMul() 计算矩阵和向量的矩阵积。 这种方法常用于解决各种数学问题。 将矩阵和向量相乘时,有以下两个选项:
- 左边的水平向量乘以右边的矩阵;向量长度等于矩阵中的列数;
- 左边的矩阵乘以右边的垂直向量;矩阵列的数量等于向量长度。
如果向量长度不等于矩阵中的列数,则会产生严重的执行错误。
为了将两个矩阵相乘,它们的形式应当如下:A[M,N]*B[N,K]=C[M,K],即左侧矩阵中的列数必须等于右侧矩阵中的行数。 如果维度不一致,则结果为空矩阵。 我们通过示例查看所有矩阵相乘的变体。
void OnStart() { //--- initialize matrices matrix m35, m52; m35.Init(3,5,Arange); m52.Init(5,2,Arange); //--- Print("1. Product of horizontal vector v[3] and matrix m[3,5]"); vector v3 = {1,2,3}; Print("On the left v3 = ",v3); Print("On the right m35 = \n",m35); Print("v3.MatMul(m35) = horizontal vector v[5] \n",v3.MatMul(m35)); //--- show that this is really a horizontal vector Print("\n2. Product of matrix m[1,3] and matrix m[3,5]"); matrix m13; m13.Init(1,3,Arange,1); Print("On the left m13 = \n",m13); Print("On the right m35 = \n",m35); Print("m13.MatMul(m35) = matrix m[1,5] \n",m13.MatMul(m35)); Print("\n3. Product of matrix m[3,5] and vertical vector v[5]"); vector v5 = {1,2,3,4,5}; Print("On the left m35 = \n",m35); Print("On the right v5 = ",v5); Print("m35.MatMul(v5) = vertical vector v[3] \n",m35.MatMul(v5)); //--- show that this is really a vertical vector Print("\n4. Product of matrix m[3,5] and matrix m[5,1]"); matrix m51; m51.Init(5,1,Arange,1); Print("On the left m35 = \n",m35); Print("On the right m51 = \n",m51); Print("m35.MatMul(m51) = matrix v[3] \n",m35.MatMul(m51)); Print("\n5. Product of matrix m[3,5] and matrix m[5,2]"); Print("On the left m35 = \n",m35); Print("On the right m52 = \n",m52); Print("m35.MatMul(m52) = matrix m[3,2] \n",m35.MatMul(m52)); Print("\n6. Product of horizontal vector v[5] and matrix m[5,2]"); Print("On the left v5 = \n",v5); Print("On the right m52 = \n",m52); Print("v5.MatMul(m52) = horizontal vector v[2] \n",v5.MatMul(m52)); Print("\n7. Outer() product of horizontal vector v[5] and vertical vector v[3]"); Print("On the left v5 = \n",v5); Print("On the right v3 = \n",v3); Print("v5.Outer(v3) = matrix m[5,3] \n",v5.Outer(v3)); //--- show that the product of matrices generates the same result Print("\n8. Outer() product of the matrix m[1,5] and matrix m[3,1]"); matrix m15,m31; m15.Init(1,5,Arange,1); m31.Init(3,1,Arange,1); Print("On the left m[1,5] = \n",m15); Print("On the right m31 = \n",m31); Print("m15.Outer(m31) = matrix m[5,3] \n",m15.Outer(m31)); } //+------------------------------------------------------------------+ //| Fill the matrix with increasing values | //+------------------------------------------------------------------+ void Arange(matrix & m, double start = 0, double step = 1) // the function has three parameters { //--- ulong cols = m.Cols(); ulong rows = m.Rows(); double value = start; for(ulong r = 0; r < rows; r++) { for(ulong c = 0; c < cols; c++) { m[r][c] = value; value += step; } } //--- } /* Execution result 1. Product of horizontal vector v[3] and matrix m[3,5] On the left v3 = [1,2,3] On the right m35 = [[0,1,2,3,4] [5,6,7,8,9] [10,11,12,13,14]] v3.MatMul(m35) = horizontal vector v[5] [40,46,52,58,64] 2. Product of matrix m[1,3] and matrix m[3,5] On the left m13 = [[1,2,3]] On the right m35 = [[0,1,2,3,4] [5,6,7,8,9] [10,11,12,13,14]] m13.MatMul(m35) = matrix m[1,5] [[40,46,52,58,64]] 3. Product of matrix m[3,5] and vertical vector v[5] On the left m35 = [[0,1,2,3,4] [5,6,7,8,9] [10,11,12,13,14]] On the right v5 = [1,2,3,4,5] m35.MatMul(v5) = vertical vector v[3] [40,115,190] 4. Product of matrix m[3,5] and matrix m[5,1] On the left m35 = [[0,1,2,3,4] [5,6,7,8,9] [10,11,12,13,14]] On the right m51 = [[1] [2] [3] [4] [5]] m35.MatMul(m51) = matrix v[3] [[40] [115] [190]] 5. Product of matrix m[3,5] and matrix m[5,2] On the left m35 = [[0,1,2,3,4] [5,6,7,8,9] [10,11,12,13,14]] On the right m52 = [[0,1] [2,3] [4,5] [6,7] [8,9]] m35.MatMul(m52) = matrix m[3,2] [[60,70] [160,195] [260,320]] 6. The product of horizontal vector v[5] and matrix m[5,2] On the left v5 = [1,2,3,4,5] On the right m52 = [[0,1] [2,3] [4,5] [6,7] [8,9]] v5.MatMul(m52) = horizontal vector v[2] [80,95] 7. Outer() product of horizontal vector v[5] and vertical vector v[3] On the left v5 = [1,2,3,4,5] On the right v3 = [1,2,3] v5.Outer(v3) = matrix m[5,3] [[1,2,3] [2,4,6] [3,6,9] [4,8,12] [5,10,15]] 8. Outer() product of the matrix m[1,5] and matrix m[3,1] On the left m[1,5] = [[1,2,3,4,5]] On the right m31 = [[1] [2] [3]] m15.Outer(m31) = matrix m[5,3] [[1,2,3] [2,4,6] [3,6,9] [4,8,12] [5,10,15]] */
为了更好地理解矩阵和向量类型是如何排列的,这些示例展示了如何使用矩阵代替向量。 这意味着向量可以表示为矩阵。
“complex(复数)”类型的复数
struct complex { double real; // real part double imag; // imaginary part };“complex” 类型可以作为 MQL5 函数的参数按值传递(与普通结构不同,普通结构只能通过引用传递)。 对于从 DLL 导入的函数,“complex” 类型只能通过引用传递。
后缀 “i” 用于描述复数常数:
complex square(complex c) { return(c*c); } void OnStart() { Print(square(1+2i)); // a constant is passed as a parameter } // will print "(-3,4)" - a string representation of a complex number复数只能进行简单的运算: =, +, -, *, /, +=, -=, *=, /=, ==, !=。
不久之后将增加对其它数学函数的支持,从而能够计算绝对值、正弦、余弦、等等
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/9805
新文章 MQL5 中的矩阵和向量已发布:
作者:MetaQuotes
欢迎与我交流投资哲学,微信号:hgb2022168