EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
前言:众所周知对于循环这种运算,matlab的运算速度是不快的 想起来个冷笑话,黑客帝国里的主角呢奥之所以能快过子弹,因为Matrix是matlab写成的hhhh 因此将循环部分用C语言写,然后编译成matlab可以调用的mex文件,无疑可以加快循环运算速度,从而加快整个代码速度 之前因为合并数据需要不会数据库,强行在matlab里利用类似excel的vlookup功能,无奈太慢,只能想办法最后知道了这种方法,最近偶然在桥哥的知识星球里又提到了,也顺便复习和记录一下。 ps:今天在闲鱼上买了小车车,高兴! 1.环境配置我的是matlab2019a,win10-64bit,c语言编译器我选的是TDM-GCC(gcc/g++),安装起来很简单,推荐matlab2015及以后的选择这种,详细安装过程可以见文末链接1中的For Matlab 2015部分
, v+ U2 j# K8 W# n; Y" C g. H
2.如何编写可以被编译成matlab可执行文件的c语言代码我是在matlab中文论坛(地址见reference第2条)里找到如何编写的,不过他写的有点乱,我来消化后写一下自己的理解 mex接口函数跟一般的C语言文件主要是两点区别, 第一是必须引入头文件mex.h #include "mex.h"第二是多了一个叫mexFunction的函数 void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])举个栗子:
+ f% g+ ]1 }8 i) |& f' D. a; [, o# F9 ]3 s5 @. D2 |0 k
#include "mex.h" // 使用MEX文件必须包含的头文件
. a4 H( s( E- w# A+ c" V. N9 V
% q/ U m: ~. s" h$ x. s. B" l4 w( I- : v+ n9 T! a! K0 O
& a" P; U- d( {
// 执行具体工作的C函数
( v7 @" z; u$ Z# G% ^2 I0 Z p" N: g+ x5 |
- 8 M2 o, O8 K; k+ g' A) F$ a3 P$ m% Y& o
! L' Y% q( P6 R( ^/ [* l
double add(double x, double y)
$ r3 u( S4 j7 |& H5 c- L4 P* E6 [0 ~; K$ O9 j3 \
% i' M4 @6 L$ B3 u* p% _8 I, d, B) |
{
3 Q1 N7 z: P; _( G' ^' @* P5 S( X2 a% C* y, q& |: O0 k) ~, F1 i
- I( F2 b4 j6 b' b- ^
; I, A: a' u+ C return x + y;9 u4 q3 a1 _1 J5 s/ b& _8 W+ W
6 \! D8 [" ^/ J8 Y7 I. ~6 e- # k- U/ @5 S6 e+ v" j
K& q+ l$ N! T2 H$ g L1 ^
}, a& z. U: ^+ | m3 l4 N# i
* z) r$ F* K- q% |" F
8 r' E R% g- q* T* ]# ?
* m7 Y* c* F9 v. T// MEX文件接口函数
9 K# L# W% L( s- ?, y2 Z
" U( i8 G, c* X1 v/ w
% n. p& \) D: H( [6 }' S K; [ I
void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])
* t" k8 L3 H3 e0 V; D/ c4 O: c! G7 i( l1 Y) L5 q
- 9 S0 R$ E8 V7 Q! f* w
4 T5 g/ D3 ]+ J% H$ L2 x{
! w5 M: G+ Y! o8 {% I4 I
8 p; B& k, t# ]) j% |- K
6 o& A! u% ~7 @4 {! w9 j' `; D) G) m( O3 _) X) H6 ?4 {- U
double *z;
$ G) A0 _, ]! i' H( R; v( ~/ u- i, X: M
% G0 D8 A. G) |) O/ ~5 V; E8 r5 P, r6 m& [; U( F
double x, y;5 s$ I) m& {) Y: y5 C b, y
( N3 h; W/ x: [9 q; E- _. ^! _- + n/ G: n; G; `7 p% o( k
8 e# R0 o# Z* i: I+ L8 \ plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
5 }3 ^ K2 z" D4 x4 p5 v3 n' ^0 L0 T, _5 G( M& d
3 W2 z- R( K% V7 l4 E8 C* J4 f, Q4 P9 p9 {% X( d9 ~
z = mxGetPr(plhs[0]);
7 G! [7 Y" D0 V, M& X: I* w( _& w$ e+ @. W
- 1 E5 b5 @9 }. S0 Q4 [
/ a7 a6 n8 w" \ x = *(mxGetPr(prhs[0]));0 Q/ z$ m- [5 R% f) b- w1 Y
( }( @% o$ P8 [% s" f
- ' F9 [$ e! Z5 d* j9 Q
$ f, s7 y6 |* e/ n y = *(mxGetPr(prhs[1]));0 x; r/ I: `+ R7 A: v' ~
' h3 w. c% m* v+ I% G" } - " `0 G" z; N( B2 [: A( ^' i
$ q* N& H4 [9 Q& {/ v; w/ y
*z = add(x, y);( Y* ^& v2 o# \( e. f. T1 B) T
$ @+ h: T& U+ z% e8 t D" }7 ^5 M - " j6 z+ b& D l! c: v( J7 f0 O
$ g( c. e/ G; j}) R3 d/ K3 {, R; k! V, X+ X
9 e+ I7 h$ ~. m* f; s# `* a
9 s/ e6 S' [% c$ I; h- _; l( v" V/ y
也可以写成: - & {" z9 a% r8 L
7 }& G4 t9 _+ I* Z6 q/ e#include "mex.h" // 使用MEX文件必须包含的头文件3 h X+ r5 d$ m0 n
, v" [4 }: D' L7 b8 |, \9 P
# e4 @! A9 D8 T; i( V$ G
, l8 c w+ _" o V4 a// MEX文件接口函数
, n. g' l/ T+ m s! }1 N* x5 x3 ^
- * I6 J! J v6 G5 h. M0 Z0 o& t
4 ?6 ?' H% t3 ^1 q6 @void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])/ R+ W3 }% u7 N6 O& h8 O( [
" X+ }# Y0 R, c+ N: q
- $ V* Y& D' d7 s; y4 c& x* z' T
1 \3 b! i3 d, d4 H; K/ |{! [% g$ z* j( L. X+ g: W+ }
4 u& p9 [0 f/ l; C! h9 c - ! i, y+ ~4 I' I
7 V* |( L: G7 m0 s: r" m double *z;6 \0 L3 k/ [7 f# L+ S* \/ J/ t9 `
: m) c" v1 Y" w% W8 W3 ~# `% S
$ D. Q. V7 `& u0 V2 Z
! n; i2 m( b* i* \ double x, y;, s7 C$ }$ H$ s2 f* w2 N7 D9 g
/ s2 t4 v4 q8 N' m2 @
4 C$ A/ a7 x i% W# j1 S8 o4 Y$ W3 E
) c: A) A8 }9 }2 r4 R6 T5 C plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
# Y1 Q0 t* k, m/ Y( {' k; m* Q) ?/ {1 B! S1 y
- " w' p% u5 [6 p9 U! v4 U
7 r, h( d& h3 w' r" N
z = mxGetPr(plhs[0]);; b9 ^4 d/ r) X: V/ Z- [1 ]! D( ^
6 N; A; \7 r8 o! X6 H - $ W( C/ g! e# e* c: o a
$ k; _9 ?( _5 c6 \; w& C x = *(mxGetPr(prhs[0]));% I: G {2 j' \
) g% n# D$ [- s5 C
! K; O \3 }: P( S5 Z6 O- x/ \6 g. o0 v
y = *(mxGetPr(prhs[1]));8 l0 w1 d+ x" R1 S6 Y
4 `& s5 V; R% x) G& T1 I$ w- ! l8 Z l& s, i3 j# Q
6 h5 m% N/ X; T) q# |2 s
*z=x+y;5 H# g: V4 g/ l9 Y8 f I1 G
f. L3 r4 h% f+ \. N# T3 w
- 5 |' c5 R* F2 v2 R6 S: S
1 n% [5 U3 ~8 f! Y1 h* W}
6 K1 o G9 B' y! g; O8 |) A% j
4 u1 A/ B) O1 C: S6 } Q- O, g. n! ]3 q: Y' b: b; {1 Y: S! n* A6 P' F/ z
也就是说执行具体功能可以通过编写一个独立的c语言函数在接口函数里调用,也可以直接写在mexFunction接口函数里 我个人推荐将具体功能独立出来,这样一来: c语言函数负责执行具体功能 mexFunction接口函数负责数据的输入输出(将matlab数据输入c语言环境,运算后再输出回matlab)形式组织 再调用c语言函数
分工明确。 于是关键问题就是如何编写mexFunction接口函数了 void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])下面解释一下mexFunction各个参数的含义(这里看到是void,即无返回值,因为传值是通过指针数组plhs[]传出的) 参数 意义 英文全称 类型 % f2 d9 [9 e5 i: E; h. h
nlhs左边输出参数的数目number of left-hand side整型(int)4 h( z4 i* a$ s' b4 J0 r: Q/ @
plhs指向输出参数的指针pointer of left-hand side指针数组/ x5 R8 m$ Q$ y2 ~
nrhs右边输入参数的数目number of right-hand side整型(int)
- k- n) d% Y; A6 `# U3 \$ L- Yprhs指向输入参数的指针pointer of right-hand side指针数组8 q C. v( S6 S K& _
第一个参数nlhs是输出参数的数目,第二个参数plhs是指向输出参数的指针 第三个参数nrhs是输入参数的数目,第四个参数prhs是指向输入参数的指针 其中plhs和prhs类型都是指向mxArray类型数据的指针,prhs这里还加了个const,这里的const跟之前c语言中是一样的,代表不改变,因为prhs是指向输入参数的指针,mxArray这个数据类型是在头文件mex.h中定义的,in fact ,在matlab中大多数数据都是以这种类型存在。 还是拿之前的栗子来解释:
[- z O1 I) j! N" n
# {) j& I7 ~; l; R* t K, D#include "mex.h" // 使用MEX文件必须包含的头文件2 @& d' u# Q# m4 d- h, {* H
. m* D$ T9 I" g( t- 3 v# A0 C- h4 t
7 b! p( j& m3 e' B- ?// MEX文件接口函数
E7 o ^4 ]) l: _- R
4 J" b" r7 Y. {: _7 K; ?& i - " \1 B% z Y9 a8 q. M3 f
7 V6 k# o8 @% r- Q& Q$ _void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])
( `! b/ i. Y3 B6 L' `; d# s+ K1 m7 o
1 x/ A; x/ e! Q1 w6 W" A* w
# U+ S P) N: U# z0 x* Q/ {& Q) q{) J& j, t4 T9 k7 G: D. A! \" P
4 ^- t B$ E( O3 @/ f- ( }8 }# D$ G1 l% G) d" A
) v1 i, m8 F+ m, I$ g# {+ e
double *z;
8 H) S) K) Q7 e* z. {. |1 `9 D5 ]6 i" x
' A! d' Z ]# }& i; m( v' ~/ i. J( n z) A& K. l1 s
double x, y;
) x5 c' J4 M+ ^3 R' M0 x/ m6 D9 V7 j+ _- e& H( h# E: o
- ) Y& ]4 N7 n" f
\/ {$ r" Y U
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
+ n9 ]8 m8 ~9 @
$ G" q& @- a6 g - 2 y, ]! B. }2 U$ m: C: \
% m, e+ \- o; e9 u z = mxGetPr(plhs[0]);' t$ _' P$ @; A% m H
5 F9 r3 a ?. h* q; \- |
. U1 |( g! S! T. |1 P9 m! r6 l4 g3 P2 A9 ?/ Z2 G
x = *(mxGetPr(prhs[0]));
9 w+ N# ]- J2 v2 P+ E3 J/ r) |: a$ F* x# K! f/ a0 f6 p
- - _; `' g% Q8 n4 m
8 Q9 r% {- U' p! O& y
y = *(mxGetPr(prhs[1]));
! o z6 G+ ]5 f( [
0 A( Q+ t) o4 _; t3 [ - - b& v0 q! H' a9 T1 P1 M
% _' ]: i$ Y6 k2 T3 C! g( u
*z=x+y;- n2 ?, M9 }* M: d" E4 }0 @
" D7 n" \0 f+ P
; a5 I0 j; G' P5 Z3 ?
4 @" w2 f/ A& ~0 z; b& k}
9 { g7 l+ n( k4 a6 B1 |5 [% B
% T$ z" y) k0 o- S& Z3 G& ?
' s" S4 }. K" [" }/ t* C: Y
在这个栗子中,输入参数是x,y,输入参数是z(虽然没有返回) plhs和prhs其实都是指针数组 prhs[0]代表指向第一个输入数据的指针,mxGetPr代表获得这个指针,后面再加个*就是c语言里面再正常不过的按指针取内容了 所以就这样x,y通过下面这两句传入到了mexFunction中
3 n- R3 Z0 I' e. X4 {* d* |3 U5 c# J" _8 X+ W$ `
x = *(mxGetPr(prhs[0]));9 f0 C5 |- b h7 s2 l+ |1 y6 a
Y/ D1 b$ r! s
- f% n$ X% M9 e& e9 M4 y, A1 z) o M c3 [" |$ W
y = *(mxGetPr(prhs[1]));+ u2 i2 \; I0 H6 P( v
Q( _/ h/ B T9 i& R. G
3 S0 e0 p" H% D: G% v0 P5 _0 @
mxGetPr函数的功能是从指向mxArray类型数据的指针prhs[0]、prhs[1]中获得了指向double类型的指针 另一个函数是mxGetScalar,Scalar即标量,功能是把通过prhs传递进来的mxArray类型数据的指针所指向的数据(标量)赋给c程序里的变量。前面的mxGetPr是传递矢量的,否则矩阵或者向量就没有办法传进来 这里由于传入的每个参数是单个值,于是也可以用mxGetScalar改写:
% D- n# z5 W$ K: B$ ?0 M
' ~/ z- {: ]; q' }8 n/ v#include "mex.h" // 使用MEX文件必须包含的头文件. M. j! G. g; X' w
. _- C5 z) ?7 k- c5 s P* K
* q; V( [ v6 L& h: ?# b* T; i% F* X
// MEX文件接口函数
( X( c- I0 v$ e7 x% e4 a! D3 E$ a) t. f/ j+ Y
5 J* s- i0 \, C% W; y% q, J, k+ W# j! a
void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])
8 o9 O) o# t' N, N: m+ K( q
2 R9 r7 b6 c6 B ?! l& ^" H! b4 P) x- ) v# H* f7 o* M% h* ~9 K& n' S
+ {" ]8 S0 | S1 R# {/ D/ l
{
- S8 o& F0 [" K; n$ E5 e5 M& c F. B9 v9 }
- 8 ]4 e2 _2 |$ Y! x. d& |: i+ j
x- n- g+ n5 O# p+ W double *z;
: l" O$ P$ D0 i2 P0 {" `" ^; P9 I, y) q; X: K
" e7 A3 k) E: V# _
- c9 s9 M3 L& ]0 L double x, y;
' p/ x: B0 n8 U; \: V& T# R) t" y7 _+ a/ ]9 k) ~ h
- * }( u* _! P) s
- @- l6 X2 I$ q3 G plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
' m% t4 U/ K* C: r3 q+ E8 _& x, F# q+ \( T
4 }( @) K1 w/ q7 U( ^) N
1 A/ T! f2 S' w. Z
% ^* L+ S* s8 g$ e1 w H& H! y z = mxGetPr(plhs[0]);& f) X, k1 S7 A, n4 S
+ `: Y: }: Z4 i, ~
& m' d" R5 x/ R' u8 D
2 P8 u+ v8 [) J/ {$ V x = mxGetScalar(prhs[0]));( U- b* |1 t! J" x: n. k
: e. A9 m& ~3 a! d3 W- }- U5 j" t& L0 U6 Y+ W8 V7 I
# E- ], N5 o5 t* P y = mxGetScalar(prhs[1]));, Y( I% j: `# L. @
& d7 g* H' m( [ r$ B - % y a: b( U8 q4 C+ h
4 U: h# a* p2 \
*z=x+y;
8 \# N5 o8 P( }, ]: f* D
4 C& P* b, ^+ `/ J
$ k: M( H6 z( m# }& X1 k
$ ]6 l e1 C4 F6 e# X}+ n5 C& f: |+ U7 ?9 t9 ]2 m
4 b7 V7 R' H* a2 ]- e# A- U' I7 q! ^9 Y, q$ e
(注意:输出参数因为需要通过指针传出,因此这里z必须用mxGetPr这个函数来从mxArray指针获取double指针) 但是这样还是有个问题:如果输入的不是单个的数据,是向量或者矩阵,即使我们通过mxGetPr获得了矩阵或者向量的指针,但是我们假如不知道矩阵的shape,还是不好取值或者计算,所以这里又有两个函数mxGetM和mxGetN可以通过传入参数指针获得传入参数(矩阵)的行和列数。 需要注意的是: 在matlab中矩阵的第一行和第一列的序号是从1开始的,而在c语言中是从0开始的,而且在c语言中的一维数组存储矩阵的数据时,是一列列从上到下,从左到右来存储的,也即 matlab中一个m*n的矩阵M(i,j)对应于c语言中一维数组N中的N[j*m+i]
举个栗子: - 9 w1 ~: z- t) Z
; S3 a$ h5 {: e: Q! ^2 Z& C
#include "mex.h"
" H" q6 {# }( w) ], k* F" U3 m# f
) L) x& S8 f. G* T [( H/ @" g - $ ]9 M& [1 {( z0 r
) @8 j! P; ]6 Y8 z
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
' c* C( n+ A$ p+ Z2 s3 S0 f( d( E% V9 k2 s3 S3 k+ x7 ~
5 r. M% M! K k! F) `7 u0 V7 p7 ^% T* C9 ^" \
; C3 ]; m6 |0 J2 i
4 u. D K8 M( d F. ~ ~1 d% Y
2 @% x+ ` }, c& s! U$ U6 s( N% ]/ L
double *data;" _( w1 L$ T- E2 l8 P3 y" i
5 t* W! o' @) o) i! o
9 }, c7 }4 w! Z
2 H# ?0 c6 E" g2 Uint M,N;8 ^0 N3 U3 L2 D+ R
9 M8 A& x7 W5 Y% l3 z0 Y# A2 X- ) }: s- D, f( U4 L6 L6 L
" ^* y7 A, K2 Z! \' ^int i,j;
" H$ A) G9 U2 G3 s5 l1 w! E |3 z! C" z+ N- o2 S; M- Y+ T
- * Y, N3 l( Q3 ?6 T4 D* _6 `
4 ~! v+ B; M6 q. g, R9 bdata=mxGetPr(prhs[0]); //获得指向矩阵的指针
0 s* G1 S, C; v& K/ {1 l& c
( o; i# }0 P2 }$ q9 K4 i, Y. @ - 5 G5 ^9 n! _0 n/ O; z* D
0 J3 g7 b7 F; s! o' wM=mxGetM(prhs[0]); //获得矩阵的行数! a; F9 d( n6 r8 F
9 @* T! R2 `$ M. L
' |+ i8 b x9 q" N7 I0 l- l1 E$ S2 D( T( H# P" v- E' U6 d
N=mxGetN(prhs[0]); //获得矩阵的列数
1 @1 i( B: u0 y4 d, K( E, U
! J6 L# I& N( e& h7 ]0 q/ Q- , V& a: ~" ]0 A3 @5 s8 G; m' u; D1 y
4 H6 n3 y. U" u) A- D. P: X( C6 |
for(i=0;i<M;i++)+ r I. U5 h6 _& ?- \, r( o
$ M2 _0 W) `$ ~/ V, X# j8 R* \
4 s6 L9 V0 M6 M6 _- [
4 u% n% S9 x. S5 n{. y* R+ d2 @; r5 n$ ~5 I4 B. t
! Y% ^$ h& E; l5 `9 v5 A
. F/ B" T- F1 M# v4 f) [. v: v% I3 C+ I8 [5 Q) K
for(j=0;j<N;j++)% a& Q+ ]: t y( i# \3 X
8 G3 P2 `/ K5 k1 U" W- O! ~- Z, L
% z9 }. M$ e7 M0 z, s5 W
8 G8 i& h/ Y/ c mexPrintf("%4.3f ",data[j*M+i]);
; j9 X5 R) m- e5 L# R4 s# K7 `' D/ w
% c0 u# h. L# L! `' a% j. J
# L2 m# U& u+ R$ P% d" E$ M& `, r" H& c
mexPrintf("\n");
7 m& n. o* p* ]4 E- O' Q" B5 d8 |' J2 S5 V V
- 8 b$ `1 Q; p+ [/ S) s8 j; P
) @9 W5 B/ U& l: {7 z* r}6 Y% u! d; @: e, g2 `7 s+ k2 P
6 f% m+ U! t( p0 l7 ^2 O
* a" O" g" \. m% K' e9 s( O! y
; q, o# W+ I6 a# j }7 `" r* [0 T% Y; a
. r! k) N9 J, f4 s* x
% H* D7 t. G; M u/ f: z
假如是一个形如[1,2,3;4,5,6]的矩阵,则执行上述后会先后打印出1,4,2,5,3,6 以上讲的都是输入参数,由于输入数据在函数调用前就已经在matlab里申请过内存,由于mex函数与matlab共用一个地址空间,因此通过prhs传递指针即可传入输入参数。但输出参数却需要在mex函数里申请内存,才能将指针放在plhs中传递出去。由于返回指针类似必须是mxArray,所以matlab专门提供了一个函数:mxCreateDoubleMatrix来实现内存申请,函数原型为: mxArray * mxCreateDoubleMatrix(int m,int n,mxComplexity ComplexFlag)m,n分别是待申请矩阵的行数和列数,需要注意的是为矩阵申请内存后得到的是mxArray类型的指针,就可以放在plhs[]中传递出去了。但是对这个矩阵的处理(包括赋值)却需要在mex函数或者c语言函数中完成,这就需要通过前面的mxGetPr或者mxGetScalar。使用mxGetPr获得指向这个矩阵的double类型指针后,就可以对这个矩阵进行各种操作和运算了。 还是拿这个栗子讲,这里由于输出是一个数,于是m,n都是1,通过mxGetPr进一步获得指向double数据类型指针z
& ?- H3 l2 y% D/ P$ o8 O" i" K4 o( L7 Q( n, _# D' G
7 U, H3 S* T+ g8 J+ W J4 X; ~, _
4 d9 L7 y. p" V" W1 a1 V
/ D6 \; t: x) Y/ o) ?2 g$ l! Y9 T ?9 d1 F# h+ U/ x8 h
double *z;
% g. F2 Q$ T- E8 p5 ]
0 L3 ?$ y- w# E1 x/ ]% M* }7 q' P N
6 f6 g+ `6 X* j7 Q
! l, H0 W! u! B1 T V plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
$ i! ~# [% M9 p9 p t( V7 J% x, y9 E! L! v
7 Q, [& g+ G' d% N+ T
$ r- h/ P$ u+ x! o* x! G+ b! o3 [ z = mxGetPr(plhs[0]);
! x7 C. k0 W% P7 f' y/ k6 y0 D* q
# X ^6 Z: C, ?, x& z. }! e; M2 j: S. w* A$ D/ ]- @% {2 k3 @9 j
x = *(mxGetPr(prhs[0]));- s% a1 n. K3 a1 V4 U
2 u+ r1 S6 D7 s/ m% ]& D* I- ) W- |* |1 L& _- } \4 O) a
: n& I' T# G# y) P6 C. ^' Z y = *(mxGetPr(prhs[1]));
8 K6 U1 m4 T' n8 D* X* ]6 e& h
$ H: v. N1 w+ y# B" u" t1 o( N% C - ( w$ f9 H! P7 r) U3 k% Y
5 S' h4 K) J* Z% Q5 W9 U *z=x+y;
$ v+ k6 Q* j, \$ C! y+ D! c2 B4 Q% E+ W0 S
. ^* y. A$ o5 }1 C5 T; b3 ?
当然,matlab里使用到的并不只是double类型这一种矩阵,还有字符串类型,结构类型矩阵等,并也提供了对应的处理函数。
) g, P% K) C0 K5 _; s |