4

swap: Matlab 中交换两个变量

 3 years ago
source link: https://zhiqiang.org/coding/swap-variables-in-matlab.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

swap: Matlab 中交换两个变量

作者: 张志强

, 发表于 2009-05-10

, 共 2387 字 , 共阅读 707 次

Matlab 程序效率低下,其中一个原因就是它的参数无法引用,每次都是传值。这不但导致效率问题,要实现某些功能,也需要一些特殊的手段。比如最简单的,如果交换两个变量的值,也就是在 C/C++里的函数 void swap(int& a, int& b),在 C/C++里实现很容易,但在 Matlab 里,你会吗?

下面这个解决方法很巧妙,因为它的实现很有参考价值(来源,可以下载.m 版本),附在下面欣赏一下。

function swap(A,B)
% SWAP - swap contents of two variables
%   SWAP(A,B) puts the contents of variable A into variable B and vice versa.
%   You can use either function syntax 'swap(A,B)' or command syntax 'swap A B'.
%
%   Example:
%     A = 1:4 ; B = 'Hello' ;
%     swap(A,B) ;
%     A % -> Hello
%     B % -> 1  2  3  4
%
%     SWAP(A,B) is a convenient easy short-cut for other (series of)
%     commands that have the same effect, e.g.,
%       temp=A ; A=B ; B=temp ; clear temp ;
%       [B,A] = deal(A,B) ;
%     The advantage over these two methods is that using SWAP one does not
%     have to declare intermediate variables or worry about output.
%
%     See also DEAL

% Tested in Matlab R13
% version 1.1 (sep 2006)
% (c) Jos van der Geest
% email: [email protected]

% 1.1 Use <deal> to swap (insight from Urs Schwarz)
%     Added command syntax functionality (suggested by Duane Hanselman)
%     Modified help section 

error(nargchk(2,2,nargin)) ;

if ischar(A) && ischar(B),
    % command syntax: SWAP VAR1 VAR2
    evalstr = sprintf('[%s,%s] = deal(%s,%s) ;',B,A,A,B) ;
elseif ~isempty(inputname(1)) && ~isempty(inputname(2)),
    % function syntax: SWAP(VAR1,VAR2)
    evalstr = sprintf('[%s,%s] = deal(%s,%s) ;',inputname(2),inputname(1),inputname(1),inputname(2)) ;
else
    % No valid command syntax, force error
    evalstr = '[:)' ;
end
evalin('caller',evalstr,'error(''Requires two (string names of) existing variables'')') ; 

另外附 Matlab 参数传递的方式(来源):

Matlab 使用的是一种叫作"copy-on-write"的矩阵拷贝构造函数,假如你定义了函数

function myfun(A,B)
do something

并在主程序中调用了myfun(Amat,Bmat),此时程序并不是把 Amat/Bmat 的内容全部复制给 A 和 B ,而是新建两个局部变量 A 和 B ,这两个变量的数据部分通过两个指针分别指向 Amat 和 Bmat 数据段进行共享数据,并把 Amat/Bmat 中的一个叫作 refcnt(reference count)的变量加一。这样避免了拷贝大量数据的开销。

在 myfun 中,如果你只读取 A 中的数据,此时,使用 A 完全等价于使用 Amat 中的数据, 但如果你需要修改 A 中的数据,此时 Matlab 先检查 A(Amat)的 refcnt ,如果这个数大于 1,则说明除了 A,还有其他矩阵也同时共享这个数据,为了保证这次修改仅对于 A 有效,这时候 Matlab 才会在内存中复制原来 Amat 的数据内容给 A ,然后修改 A 中的数据。此时 A 已与 Amat 分离。

大多数 C++矩阵类都是通过 refcnt 的机制来进行复制的。

如果有大量参数传递,可以考虑写 c mex/fortran mex ,也可以使用 global ,还可以用evalin(WS,...)

Q. E. D.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK