MATLAB 有什麼奇技淫巧?


下邊所有例子如無特殊說明都是在 2016a 上執行,其他版本或有差異,建議自行測試

1. 可以用 sprintfc 生成 cellstr:

&>&> a = magic(3);
&>&> b = sprintfc("%d",a)
b =
"8" "1" "6"
"3" "5" "7"
"4" "9" "2"

2. strfind 可以作用於數值數組用於查找子串的位置:

&>&> k = strfind([2 7 1 3 0 7 1],[7 1])
k =
2 6

3. 可以用 cell 和 函數句柄實現類似於函數式編程的操作,以 fibonacci 數列為例:

&>&> f = {@(f,n)1 @(f,n)f{(n&>3)+1}(f,n-1) + f{(n&>4)+1}(f,n-2)};
&>&> fib = @(n)f{(n&>2)+1}(f,n);
&>&> fib(20)
ans =
6765

類似的,構建 if 函數:

&>&> iff = @(varargin)varargin{find([varargin{1:2:end}],1)*2};
&>&> x = 3;
&>&> iff(x&<1,1,x&<2,2,x&<3,3,x&<4,4,x&<5,5) ans = 4

4. regexprep 當替換字元串為 ${cmd} 動態表達式時 cmd 可以訪問調用時的 caller 工作區:

% haha.m
function x = haha
x = str2double(regexprep("1","1","${num2str(y,16)}"));
% command window/命令窗口
&>&> y = pi;
&>&> haha % 注意此處調用 haha 函數時並未傳入 y 的值
ans =
3.14159265358979

5. 在 2015b 或 2016a 可以啟用被隱藏的單一維度拓展:

&>&> builtin("_useSingletonExpansion",1);
&>&> (1:3)"+(1:3) % 相當於 bsxfun(@plus, (1:3)", 1:3)
ans =
2 3 4
3 4 5
4 5 6
&>&> (1:3)".^(1:3)
% 相當於 bsxfun(@power, (1:3)", 1:3)
ans =
1 1 1
2 4 8
3 9 27

除此之外許多(不是全部)的 bsxfun 用法可以簡化為上述形式。這一特性有可能在未來版本中正式發布

6. MATLAB 的一些對象,尤其是圖形對象會有一些隱藏屬性,這些隱藏屬性不能直接看到,但是如果你指定名字的話是可以訪問甚至修改的,比方說以 axes 為例,我們可以修改 axes 的 LooseInset 屬性改變其默認空隙:

&>&> figure
&>&> a = axes;
&>&> a.LooseInset = [0 0 0 0]; % 老版本用 set(a,"LooseInset",[0 0 0 0])

效果可以自己運行查看,這裡效果不是重點就不發圖了

如果你用 get(a) 或者 a.get 中只能看到一部分屬性,其中並沒有 LooseInset。 要想找到類似的隱藏屬性當然可以用 metaclass,不過更直接的方法可能是:

&>&> struct(a) % 此時要確保 a 沒有被刪除

7. MATLAB 的很多運算符可以被重載,從而實現一些比較方便的功能,之前回答過一個簡單應用的例子:matlab中有沒有類似R中magrittr包的管道操作? - 知乎用戶的回答。

這個應該不能算作奇技淫巧吧,不過知道的人可能少一些

暫時就寫這麼多吧。還有一些性能方面的,不過感覺那些不算奇技淫巧吧(個人理解是不常見的用法才算(⊙_⊙)?),就不放這裡了

----- 2016.5.9 更新 ------

8. builtin("_mergesimpts",...),這個用法這裡有介紹:Return Unique Element with a Tolerance,簡單來說可以用來合併相近或者相同的數值的

9. anonymousFunction,這個函數功能和 str2func 基本相同,但是他接受兩個輸入,經過嘗試,如果第二個輸入是 "base" 的話不管該函數在哪裡調用都可以利用 base 工作區中的變數構建匿名函數:

% haha.m
function f = haha
f = anonymousFunction("@(x)sin(a*x)","base");

&>&> a = 2;
&>&> f = haha; % 此處並未傳入 a
&>&> f(3)==sin(2*3)
ans =
1

10. ismembc ,ismembc2 和 builtin("_ismemberhelper",...)

這三個函數都是對有序數組進行二分查找,第一個返回邏輯判斷值,第二個返回元素在有序數組中的位置(如果有重複的就返回最後一次出現的位置),第三個可以返回上述兩個參數(不過第二個是返回首次出現的位置),舉例說明:

&>&> ismembc([1 3 5],[0 1 1 5 7])
ans =
1 0 1
&>&> ismembc2([1 3 5],[0 1 1 5 7])
ans =
3 0 4
&>&> [in,loc] = builtin("_ismemberhelper",[1 3 5],[0 1 1 5 7])
in =
1 0 1
loc =
2 0 4

需要注意的是,如果第二個輸入不是單調遞增不會報錯,但是結果是錯誤的。同時,由於是二分查找,所以要比線性查找 find(x==y,1) 或者 find(x==y,1,"last") 快很多;順便說一下,如果是行向量的話 strfind(x,y) 通常也要比 find(x==y) 要快一些,兩者都是線性查找,不需要有序的 x。

----- 2016.5.10 更新 ------

11. numel 函數可以接受多個參數的,作用可以從例子中看出:

&>&> a = rand(3,4,5,6);
&>&> numel(a,1,":",1,":")
ans =
24

這相當於:

numel(a(1,:,1,:))

不過由於後者需要先索引矩陣,所以需要的時間較長(且索引的部分越大越長):

&>&> a = rand(1e3,1e3,10);
&>&> timeit(@()numel(a,":",":",1))
警告: 由於運行速度過快,F 的計時可能不準確。嘗試對耗時更長的其他對象計時。
&> In timeit (line 158)
ans =
9.08076504322897e-07
&>&> timeit(@()numel(a(:,:,1)))
ans =
0.00272672929522135

當然啦,就算不知道第一種用法一般也不會有人用第二種用法,完全可以用 size 函數的結果計算

12. cellfun(函數名,....),函數名可以是以下幾個字元串:

isempty, islogical, isreal, length, ndims, prodofsize,size, isclass

其用法在 cellfun 的文檔中 Backward Compatibility 有介紹,其實功能都很簡單,但是好處是他們比對應的函數句柄要快很多:

&>&> a = repmat({[],"1";23,23},100);
&>&> timeit(@()cellfun("isempty",a))
ans =
0.000205790268896228
&>&> timeit(@()cellfun(@isempty,a))
ans =
0.0268502837700468

13. profile 的 memory 參數,舉例說明:

% haha.m
a = rand(3000);
b = a;
b(1) = a(1);

然後 profile 該函數:

&>&> profile -memory on, haha, profile viewer

可以看到除了原有的運行時間數據之外還多了內存數據,而且就這個例子而言,我們可以清楚地看到 MATLAB 的 copy-on-write 特性,不過這裡統計的應該只是在 MATLAB 的內存管理範圍內的內存使用情況,實際計算中有些內存開銷並不是由 MATLAB 管理,所以不會被記錄。(profile 還有一些其他的隱藏特性,更詳細的介紹可以參見 Undocumented Matlab 中的介紹)

14. 可以在 MATLAB 中使用 Java:

&>&> java.math.BigInteger(2).pow(100)
ans =
1267650600228229401496703205376

由於 MATLAB 的界面主要由 java 編寫,所以可以用 java 來豐富 MATLAB 的 GUI 功能。

此外,如果是 Windows 的話還可以使用 C#;另外最近幾個版本也可以使用 python(需要自行安裝 python)。

15. 我們知道新版本(2014b開始)的圖形界面有較大改動,其中一個改動就是可以用點運算符直接操作和修改圖形對象的屬性,例如:

&>&> a = uitable("data",magic(3));

如果要修改其中 2 行 2 列的元素為 0,老版本的話估計要這麼寫:

&>&> t = get(a,"data"); t(2,2) = 0; set(a,"data",t);

新版本寫起來就方便些:

&>&> a.Data(2,2) = 0;

不過如果想在老版本上也這麼方便的修改屬性值的話,需要對創建 a 的語句稍作修改:

&>&> a = handle(uitable("data",magic(3)));

這裡得到的 a 不再是一個數值句柄,可以直接用新版本的方法修改屬性

----- 2016.5.12 更新 ------

16. 可以用 sort 輸出的索引來生成多組隨機排序(或者不放回取樣):

tic
for i = 1e4:-1:1
a(:,i) = randperm(50);
end
toc
tic
[~,b] = sort(rand(50,1e4,"single"));
toc

時間已過 0.032115 秒。
時間已過 0.015228 秒。

這裡 a 和 b 都是 10000 組 1:50 的隨機排序

17. 直接看例子:

&>&> zeros(5,0)*zeros(0,3)
ans =
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0

18. 在一些情況下,數據滿足要求且硬碟足夠, v6 模式存取數據比較快:

function test
a = rand(5000);
tic; save data1 a, toc
tic; save data2 a -v6, toc
tic, c = load("data1"); toc
tic, d = load("data2"); toc
isequal(c,d)
時間已過 4.374425 秒。
時間已過 1.881225 秒。
時間已過 1.052394 秒。
時間已過 0.088677 秒。

19. 用 fft 加速兩個較長數組的卷積運算,這個算不上 MATLAB 的奇技淫巧,而是數學上的結論:

function test
a = rand(1,2e5);
b = rand(1,3e5);
tic, c = conv(a,b); toc
tic, l = numel(a) + numel(b) - 1; d = ifft(fft(a,l).*fft(b,l)); toc
tic, l = numel(a) + numel(b) - 1; n = 2.^nextpow2(l);
e = ifft(fft(a,n).*fft(b,n)); e = e(1:l); toc
norm(c-d), norm(c-e)

時間已過 4.580655 秒。
時間已過 0.051598 秒。
時間已過 0.030744 秒。
ans =
2.79282382379074e-07
ans =
2.78964931183402e-07

----- 2016.5.13 更新 ------

20. 更快的隨機數生成

function test
rng("default")
tic, a = rand(3e3); toc
rng(0,"simdTwister")
tic, b = rand(3e3); toc
時間已過 0.077385 秒。
時間已過 0.030155 秒。

可以把 rng(0,"simdTwister") 寫在啟動文件中

21. 有時候 floor 比 mod 更快的

function test
a = randi(1e6,1e6,1);
timeit(@()mod(a,3)) % 0.0266399306685575
timeit(@()a-3*floor(a/3)) % 0.0066731423625292

22. 邏輯數組和標量用.*

function test
a = rand(1e7,1);
timeit(@()2*(a&<.5) + 3*(a&>.6)) % 0.136814992133285
timeit(@()2.*(a&<.5) + 3.*(a&>.6)) % 0.0661509763579439

23. 邏輯索引

function test
a = rand(1e7,1);
b = a; b(1) = b(1);
tic, a(a&<.5) = a(a&<.5) + 1; toc % 時間已過 0.221105 秒。 tic, b = b + (b&<.5); toc % 時間已過 0.049953 秒。


運行完發個郵件給我。

周五晚上調好程序,用一個腳本把把好幾個程序串起來(都比較耗時),依次運行,結果分別存成不同的mat文件,運行完再發個郵件。

然後就回寢室high去了,什麼時候查收到郵件就去實驗室看看結果。


演奏卡農啊

% Cripple Pachebel"s Canon on Matlab

% Have fun

fs = 44100; % sample rate

dt = 1/fs;

T16 = 0.125;

t16 = [0:dt:T16];

[temp k] = size(t16);

t4 = linspace(0,4*T16,4*k);

t8 = linspace(0,2*T16,2*k);

[temp i] = size(t4);

[temp j] = size(t8);

% Modification functions

mod4 = sin(pi*t4/t4(end));

mod8 = sin(pi*t8/t8(end));

mod16 = sin(pi*t16/t16(end));

f0 = 2*146.8; % reference frequency

ScaleTable = [2/3 3/4 5/6 15/16 ...

1 9/8 5/4 4/3 3/2 5/3 9/5 15/8 ...

2 9/4 5/2 8/3 3 10/3 15/4 4 ...

1/2 9/16 5/8];

% 1/4 notes

do0f = mod4.*cos(2*pi*ScaleTable(21)*f0*t4);

re0f = mod4.*cos(2*pi*ScaleTable(22)*f0*t4);

mi0f = mod4.*cos(2*pi*ScaleTable(23)*f0*t4);

fa0f = mod4.*cos(2*pi*ScaleTable(1)*f0*t4);

so0f = mod4.*cos(2*pi*ScaleTable(2)*f0*t4);

la0f = mod4.*cos(2*pi*ScaleTable(3)*f0*t4);

ti0f = mod4.*cos(2*pi*ScaleTable(4)*f0*t4);

do1f = mod4.*cos(2*pi*ScaleTable(5)*f0*t4);

re1f = mod4.*cos(2*pi*ScaleTable(6)*f0*t4);

mi1f = mod4.*cos(2*pi*ScaleTable(7)*f0*t4);

fa1f = mod4.*cos(2*pi*ScaleTable(8)*f0*t4);

so1f = mod4.*cos(2*pi*ScaleTable(9)*f0*t4);

la1f = mod4.*cos(2*pi*ScaleTable(10)*f0*t4);

tb1f = mod4.*cos(2*pi*ScaleTable(11)*f0*t4);

ti1f = mod4.*cos(2*pi*ScaleTable(12)*f0*t4);

do2f = mod4.*cos(2*pi*ScaleTable(13)*f0*t4);

re2f = mod4.*cos(2*pi*ScaleTable(14)*f0*t4);

mi2f = mod4.*cos(2*pi*ScaleTable(15)*f0*t4);

fa2f = mod4.*cos(2*pi*ScaleTable(16)*f0*t4);

so2f = mod4.*cos(2*pi*ScaleTable(17)*f0*t4);

la2f = mod4.*cos(2*pi*ScaleTable(18)*f0*t4);

ti2f = mod4.*cos(2*pi*ScaleTable(19)*f0*t4);

do3f = mod4.*cos(2*pi*ScaleTable(20)*f0*t4);

blkf = zeros(1,i);

% 1/8 notes

fa0e = mod8.*cos(2*pi*ScaleTable(1)*f0*t8);

so0e = mod8.*cos(2*pi*ScaleTable(2)*f0*t8);

la0e = mod8.*cos(2*pi*ScaleTable(3)*f0*t8);

ti0e = mod8.*cos(2*pi*ScaleTable(4)*f0*t8);

do1e = mod8.*cos(2*pi*ScaleTable(5)*f0*t8);

re1e = mod8.*cos(2*pi*ScaleTable(6)*f0*t8);

mi1e = mod8.*cos(2*pi*ScaleTable(7)*f0*t8);

fa1e = mod8.*cos(2*pi*ScaleTable(8)*f0*t8);

so1e = mod8.*cos(2*pi*ScaleTable(9)*f0*t8);

la1e = mod8.*cos(2*pi*ScaleTable(10)*f0*t8);

tb1e = mod8.*cos(2*pi*ScaleTable(11)*f0*t8);

ti1e = mod8.*cos(2*pi*ScaleTable(12)*f0*t8);

do2e = mod8.*cos(2*pi*ScaleTable(13)*f0*t8);

re2e = mod8.*cos(2*pi*ScaleTable(14)*f0*t8);

mi2e = mod8.*cos(2*pi*ScaleTable(15)*f0*t8);

fa2e = mod8.*cos(2*pi*ScaleTable(16)*f0*t8);

so2e = mod8.*cos(2*pi*ScaleTable(17)*f0*t8);

la2e = mod8.*cos(2*pi*ScaleTable(18)*f0*t8);

ti2e = mod8.*cos(2*pi*ScaleTable(19)*f0*t8);

do3e = mod8.*cos(2*pi*ScaleTable(20)*f0*t8);

blke = zeros(1,j);

% 1/16 notes

fa0s = mod16.*cos(2*pi*ScaleTable(1)*f0*t16);

so0s = mod16.*cos(2*pi*ScaleTable(2)*f0*t16);

la0s = mod16.*cos(2*pi*ScaleTable(3)*f0*t16);

ti0s = mod16.*cos(2*pi*ScaleTable(4)*f0*t16);

do1s = mod16.*cos(2*pi*ScaleTable(5)*f0*t16);

re1s = mod16.*cos(2*pi*ScaleTable(6)*f0*t16);

mi1s = mod16.*cos(2*pi*ScaleTable(7)*f0*t16);

fa1s = mod16.*cos(2*pi*ScaleTable(8)*f0*t16);

so1s = mod16.*cos(2*pi*ScaleTable(9)*f0*t16);

la1s = mod16.*cos(2*pi*ScaleTable(10)*f0*t16);

tb1s = mod16.*cos(2*pi*ScaleTable(11)*f0*t16);

ti1s = mod16.*cos(2*pi*ScaleTable(12)*f0*t16);

do2s = mod16.*cos(2*pi*ScaleTable(13)*f0*t16);

re2s = mod16.*cos(2*pi*ScaleTable(14)*f0*t16);

mi2s = mod16.*cos(2*pi*ScaleTable(15)*f0*t16);

fa2s = mod16.*cos(2*pi*ScaleTable(16)*f0*t16);

so2s = mod16.*cos(2*pi*ScaleTable(17)*f0*t16);

la2s = mod16.*cos(2*pi*ScaleTable(18)*f0*t16);

ti2s = mod16.*cos(2*pi*ScaleTable(19)*f0*t16);

do3s = mod16.*cos(2*pi*ScaleTable(20)*f0*t16);

blks = zeros(1,k);

% Blank Block

blkblock = [blkf blkf blkf blkf blkf blkf blkf blkf...

blkf blkf blkf blkf blkf blkf blkf blkf];

% Base Melody

cello = [do1f do1f so0f so0f la0f la0f mi0f mi0f...

fa0f fa0f do0f do0f fa0f fa0f so0f so0f];

% So-FUCKING-Long Melody

violin = [mi2f mi2f re2f re2f do2f do2f ti1f ti1f...

la1f la1f so1f so1f la1f la1f ti1f ti1f ...%

do2f do2f ti1f ti1f la1f la1f so1f so1f...

fa1f fa1f mi1f mi1f fa1f fa1f re1f re1f ...%

do1f mi1f so1f fa1f mi1f do1f mi1f re1f...

do1f la0f do1f so1f fa1f la1f so1f fa1f...%

mi1f do1f re1f ti1f do2f mi2f so2f so1f...

la1f fa1f so1f mi1f do1f do2f blkf blke ti1e ...%

do2e ti1e do2e do1e ti0e so1e re1e mi1e...

do1e do2e ti1e la1e ti1e mi2e so2e la2e...

fa2e mi2e re2e fa2e mi2e re2e do2e ti1e...

la1e so1e fa1e mi1e re1e fa1e mi1e re1e... %%

do1e re1e mi1e fa1e so1e re1e so1e fa1e...

mi1e la1e so1e fa1e so1e fa1e mi1e re1e...

do1e la0e la1e ti1e do2e ti1e la1e so1e...

fa1e mi1e re1e la1e so1e la1e so1e fa1e...%

mi1f mi2e blke re2f re2f blkf do1f mi2f mi2f...

la2f la2f so2f so2f la2f la2f ti2f ti2f...%

do3e blke do2e blke ti1f ti1f blkf la1f do2f do2f...

do2f do2f do2f do2f do2f fa2f re2f so2f...%

so2e mi2s fa2s so2e mi2s fa2s so2s so1s la1s ti1s ...

do2s re2s mi2s fa2s mi2e do2s re2s...

mi2e mi1s fa1s so1s la1s so1s fa1s so1s mi1s fa1s so1s...

fa1e la1s so1s fa1e mi1s re1s mi1s re1s do1s re1s mi1s fa1s so1s la1s...

fa2e la1s so1s la1e ti1s do2s so1s la1s ti1s do2s re2s mi2s fa2s so2s...%

mi2e do2s re2s mi2e re2s do2s re2s ti1s do2s re2s mi2s re2s do2s ti1s...

do2e la1s ti1s do2e do1s re1s mi1s fa1s mi1s re1s mi1s do2s ti1s do2s...

la1e do2s ti1s la1e so1s fa1s so1s fa1s mi1s fa1s so1s la1s ti1s do2s...

la2e do2s ti1s do2e ti1s la1s ti1s do2s re2s do2s ti1s do1s la1s ti1s...%%

do2e blke blkf ti1e blke blkf la1e blke blkf do2e blke blkf...

do1e blke blkf do1e blke blkf do1e blke blkf do1e blke blkf...%

blkf so1e blke blkf so1e blke blkf mi1e blke blkf so1e blke...

blkf fa1e blke blkf mi1e blke blkf fa1e blke blkf re2e blke...%

mi2e mi1e fa1e mi1e re1e re2e mi2e re2e do2e mi1e do1e do2e ti1e so0e fa0e so0e...

la0e la1e so1e la1e so1e so0e fa0e so0e do1e la1e so1e la1e ti1e ti0e la0e ti0e...%

do1e do2e re2e do2e ti1e ti0e do1e ti0e la0e la1e so1e la1e ti1e ti0e mi1e re1e...

do1e do2e re2e fa2e mi2e mi1e so1e mi2e do2e fa2e mi2e fa2e re2e so1e fa1e so1e...%

mi1e so1e so1e so1e so1e so1e so1e so1e mi1e mi1e mi1e mi1e mi1e mi1e so1e so1e...

fa1e fa1e fa1e do2e do2e do2e do2e do2e do2e do2e la1e la1e so1e so1e re2e ti1e...%%

so1e mi2e mi2e mi2e re2e re2e re2e re2e do2e do2e do2e do2e so2e so2e so2e so2e...

la2e la2e la2e la2e so2e so2e so2e so2e la2e la2e la2e la2e ti2e ti1e ti1e ti1e...%

do2e do1s re1s mi1e do1e ti0e ti1s do2s re2e ti1e la1e la0s ti0s do1e la0e ti0e so1s fa1s mi1e re1e...

do1e mi1s re1s do1e fa1e mi1e do1s re1s mi1e so1e fa1e la1s so1s fa1e mi1e re1e so1s fa1s mi1e re1e...%

mi1e do2s ti1s do2e mi1e so1e so1s la1s ti1e so1e mi1e do2s re2s mi2e do2e mi2e mi2s re2s do2e ti1e...

la1e la1s so1s la1e ti1e do2e mi2s re2s do2e mi2e fa2e do2s ti1s la1e la1e so1e re1e so1e so1e...%

so1f so1f so1f so1f do1f do1f do1f so1f...

fa1f fa1f so1f so1f fa1f do1f do1f do1e ti0e...%

do1f do2f ti1f ti1f la1f la1f so1f so1f...

do1f do1e re1e mi1f mi1f do2f do2f ti1f ti1f...%%

do2f];

% cello

c1 = [cello cello cello cello cello...

cello cello cello cello cello...

cello cello cello cello cello...

cello cello cello cello cello...

cello cello cello blkf];

% violin1

v1 = [blkblock violin blkblock blkblock];

% violin2

v2 = [blkblock blkblock violin blkblock];

% violin3

v3 = [blkblock blkblock blkblock violin];

% Get dirty

s = c1+v1+v2+v3;

s = s/max(s);

sound(s,fs);

記得關注我哦(????????)


【Matlab讀取PDF文件】

我印象特別深刻的一個例子:

有一個pdf文件,裡面有四千多個數據,我需要把這些數據導入到excel中。不過這個pdf很奇怪,有點類似於ppt轉成pdf的,全選也只能選中當前頁的數據。整個過程的實現,方法有許多種。

1. 最常見的方法是,一個一個數據複製粘貼到對應單元格中。這種方法,耗時最長,人工成本也是最高的。

2. 第二種方法是,將pdf中每一頁的數據都複製粘貼到txt文件中,用matlab進行處理,然後寫回excel中。相比第一種方法,這種方法節約了更多的時間,不過還是要複製粘貼很多回。

3. 我最後使用的方法是,用Matlab寫一個腳本,實現每一頁pdf到txt的複製粘貼,然後進行數據處理,寫回excel中。這種方法是一鍵生成的,時間成本只是花在寫代碼的過程中。而且,隨著使用次數的遞增,單次使用成本遞減。代碼的重複使用性,使得這個方法顯得更有意義。

那麼接下來就來聊聊,如何實現pdf的處理(只針對非圖片格式的pdf):

1. pdf的複製粘貼

整 個過程需要藉助.vbs腳本的幫助。VBS(Microsoft Visual Basic Script Edition)是基於Visual Basic的腳本語言,不編譯成二進位文件,直接由宿主解釋源代碼並執行。簡單的說,就是所寫的程序不需要編譯成.exe,雙擊就能直接執行。

生成vbs腳本的原理,跟matlab寫txt文件有點類似,通過fopen,fprinrf以及fclose函數,就能生成任意所需的vbs文件。至於vbs腳本中寫什麼語句,就要根據你的邏輯而定了。

fid=fopen("CopyPDF.vbs","wt");

fprintf(fid,"Set WshShell=WScript.CreateObject("WScript.Shell")
");

fclose(fid);

在vbs中,實現全選的代碼是:

WshShell.SendKeys "^a"

這一句很好理解,^a表示的是ctrl + a,就是快捷鍵全選。

與此類似的,實現複製的代碼就是:

WshShell.SendKeys "^c"

此外打開一個目標文件的代碼是:

WshShell.run """File"""

關閉文件的代碼是:

WshShell.SendKeys "% {F4}"

對應的快捷鍵就是alt + F4

更多關於vbs編程的信息,可以網上搜索一下,這些腳本都比較常見。而生成完.vbs腳本之後,就是去執行這個.vbs腳本。在matlab中,執行.vbs腳本和執行批處理文件.bat的命令相同,都是:

dos(file.vbs) 或 dos(file.bat)

Matlab與.vbs文件的結合運用,使得整體所能實現的功能跨度更大更靈活。

2. txt文件的讀取

讀取txt的方式多種多樣,在這裡,我簡單的介紹下我最常用的兩種方式:

1)

fid=fopen("MIL.txt","r");

data=fscanf(fid,"%s");

fclose (fid);

通過這種方式讀取出來的結果有個特點,所讀取的結果,其數據類型是char,中間的空格以及換行信息會被忽略,不過讀取速度較快。如果對輸出結果的格式沒有特殊要求的話,優先選擇這種讀取方式。

2)

fin=fopen(filename_Model,"r");

text_line = {""};

ct = 1;

while ~feof(fin)

text_line(ct,1) = {fgets(fin)};

ct = ct+1;

end

fclose (fin);

另外一種讀取方式,相比第一種,速度會稍慢一些,輸出結果的數據類型是cell的形式,不過保留了原來文本的格式信息,包括空格以及換行。

3. excel的寫入

excel的讀取以及寫入,這個已經非常常見了,網上有非常多的帖子介紹這方面的問題,在這裡就不再重複介紹了。

這僅僅只是工作過程中的一個極小極小的例子,還有太多類似的重複繁瑣的工作。

………………………………………………

謝謝評論中幾位朋友的提醒,我才發現pdf是能直接導出txt或excel的。不過,我今天我又試了一下,由於公司電腦的限制,沒辦法導出數據文件。不過,能發現新的方法進行數據處理,也是一種收穫。

………………………………………………

如果你有興趣,可以關注我的微信公眾號"打浦橋程序員",謝謝

以上


在朋友圈看到 @石火光中的蝸牛角分享:

在command window輸入「dbstop if error」,就可以不用設斷點,在錯誤語句處自動停止並保存相關變數。而且——

還有一個生動的記憶方法:「呆逼錯了就給我停下」


1. 矩陣去重

針對多列數組矩陣的快速去重方法

% initial
sample = randi(100,1e6,4)

sample = 1000000x4 double

58 42 78 82

52 15 21 80

53 70 59 64

24 4 90 70

90 46 54 52

45 70 74 52

44 22 16 85

69 77 8 97

88 34 68 12

6 65 17 59

% method 1
tic
result_1 = unique(sample,"rows");
toc

時間已過 1.783514 秒。

% method 2
tic
col_num = size(sample,2);
hash = rand(col_num,1);
sample_array = sample*hash; % 多列轉為單列
[~,sample_filter] = unique(sample_array);
result_2 = sample(sample_filter,:);
toc

時間已過 0.315385 秒。

% assert
all(ismember(result_1,result_2,"rows"))
ans =
1

2.文件夾目錄

獲取文件夾中某類型文件

folder_dir= dir(strcat("C:Windows","*.exe"));
folder_files = {folder_dir.name}"

folder_files =

"HelpPane.exe"

"bfsvc.exe"

"explorer.exe"

"hh.exe"

"notepad.exe"

"regedit.exe"

"splwow64.exe"

"winhlp32.exe"

"write.exe"

3.子圖的總標題

subplot(121)
title("sub1")
subplot(122)
title("sub2")
suptitle("title")

4.日期格式快速轉換

% initial
sample_timestamp = repmat({"2016-05-12 14:00:00"},1e6,1);

% method1
tic
time_vec = datevec(sample_timestamp,"yyyy-mm-dd HH:MM:SS");
toc

時間已過 8.191009 秒。

% method2
tic
for i = size(sample_timestamp,1):-1:1
date_vec(i,:) = (sample_timestamp{i}([1,2,3,4,6,7,9,10])-48);
time_vec(i,:) = (sample_timestamp{i}([12,13,15,16,18,19])-48);
end
Date = date_vec*10.^(7:-1:0)";
Time = time_vec*10.^(5:-1:0)";
toc

時間已過 2.554141 秒。

5.分塊複製

kron函數最基本用法,還有很多特別的用法參考幫助文檔

sample_kron = [1;2;3;4];
result_kron = kron(sample,[1;1])

result = 8x1 double

1
1
2
2
3
3
4
4

6.mat文件部分讀取

需要使用v7.3儲存文件,部分讀取支持num/char/struct

% initial
data = rand(2,1000);
sample_struct.data = data;
sample_struct.struct = sample_struct;
save sample_h5.mat sample_struct data -v7.3
sample_struct

sample_struct =

data: [2x1000 double]

struct: [1x1 struct]

% case
data_1 = h5read("sample_h5.mat","/data",[2,1],[1,10])

data_1 = 1x10 double

0.8165 0.3116 0.2088 0.0174 0.6046 0.5704 0.5222 0.2776 0.8764 0.8880

data_2 = h5read("sample_h5.mat","/sample_struct/data",[2,1],[1,10])

data_2 = 1x10 double

0.8165 0.3116 0.2088 0.0174 0.6046 0.5704 0.5222 0.2776 0.8764 0.8880

data_3 = h5read("sample_h5.mat","/sample_struct/struct/data",[2,1],[1,10])

data_3 = 1x10 double

0.8165 0.3116 0.2088 0.0174 0.6046 0.5704 0.5222 0.2776 0.8764 0.8880

7.將mat文件導入同一個變數

result_struct = load("sample_h5.mat") % 以6中生成的mat文件舉例

result_struct =

data: [2x1000 double]

sample_struct: [1x1 struct]

delete("sample_h5.mat") % 刪除6中生成的mat文件

8.條件斷點調試

設置斷點的時候右鍵點擊該行號進入


matlab渣渣來拋磚引玉一下。

不得已使用了循環的情況下,有時運算時間會很長。這樣在調試的時候,需要判斷是的確需要很長時間,還是死循環了,最好還能估計一下要算多久。我的做法是,在最外層循環里,每次輸出一個數。例如:

for i=1:1000

i

for j=1:1000

此處省略若干行,均以分號結束

end

end

這樣在運行的過程中,就能知道已經算了多少了。


貢獻一個,應該算是常用技巧。如果你的匿名函數算出一個矩陣而你只要其中某個元素,可以定義 subindex 如下:

subindex = @ (A, varargin) A(varargin{:});

然後就可以愉快地

y1 = @ (x, t0) subindex(C(t0) * x + d(t0), 1, 1);

C: mathbb{R} mapsto mathbb{R}^{n 	imes n}d: mathbb{R} mapsto mathbb{R}^{n	imes n}x in mathbb{R}^ny_1 in mathbb{R}


分享一個:

若a為一個向量,則命令

b = a(:)

可以保證b為列向量。即無論a為行向量或列向量,b均是列向量


0. 能用矩陣操作的就不要用循環

不然你以為MATLAB這個名字是白叫的?

1. 快速交換矩陣的兩個行和列

先聲明這裡說快速是指代碼方便書寫,實際執行效率上到底快不快,我並沒有做測試。

一般的我們交換兩個變數的值總需要引入一個臨時變數,例如交換a,b的值,一般的高級語言中常見的做法如下:

temp=a;a=b;b=temp;

看下面這個語句:

A([1;3],:)=A([3;1],:)

可以實現矩陣中1,3行之間的互換,不需要中間變數,更不需要循環。稍作修改,兩列之間的互換也行,MATLAB在矩陣操作方面確實可圈可點。這個是我在看matlab官方的m文件的時候發現的,似乎是magic.m文件,大家可以用 type magic命令翻翻看。

textbooks scarcely mention this little tricky.

2. 盡量使用左除,而不是inv函數。

這個是根據Moler(對,就是MATLAB的主要發明者)先生的建議(可參考其著作《Numerical Computing With MATLAB》,中譯版是機械工業出版社的《MATLAB數值計算》),盡量使用左除,而不是inv函數,理由嘛,可能是具有更好的數值穩定性吧,不過具體是什麼,你自己去問他吧。

3. 是先列後行比先行後列快,這個 @道真也說到過,我以前也分析過這個現象。

http://379910987.blog.163.com/blog/static/335237972011716105629630/

4. 有兩種不同的求余方式

這個不算技巧吧,但是應該知道的(回字有四種寫法哦)

mod的結果是和除數的符號保持一致的,而rem則是和被除數保持一致。rem(x,y)和mod(x,y)都返回返回x - n*y,但是前者計算n的時候用的是n = fix(x/y),而後者的計算n用的是n = floor(x/y)。

5. 快速輸入之前命令的小技巧

我們知道在Command Window中按↑可以重複剛才的命令,不過有些人可能不知道,這個位置還支持搜索,假設我們一次輸入了三個命令,aaa=3; b=aaa^3; clc;然後我在Command Window中輸入a,然後按↑按鍵,aaa=3就出來了。這個在Matlab 2015及之後的版本中肯定是支持的,較早的版本我沒有測試。另外,我在Win10中測試了一下cmd,也具有類似的效果。

後面想到了再補充。


用Matlab發郵件。有時候實驗跑得很久,就可以在代碼最後加一行發郵件。一旦實驗完了就可以收到郵件。手機上綁定郵箱的話,就相當於收到簡訊了。

layumi/matlab_email_demo


先列後行比先行後列快很多


其實還真有人專門研究這個問題,不僅有專門的網站,還出了書。

傳送門:Undocumented Matlab, http://undocumentedmatlab.com/


eval()

這個應該是最有用的了,在程序中按命令行的形式運行程序。

==============================

在跑程序時,進度條可以有效地檢測運行的狀態,除了使用waitbar外,也可以在控制台顯示進度。主要是利用fprintf("")是退格操作,也可是寫fprintf("%c",8)。

如:

-----------------------------------

N = 1000;

msg = "Processed Rate: 0.0%";

disp(msg);

nmsg = numel(msg)+1;%獲得該行的長度

for i=1:N

rate = i/N*100;

fprintf(repmat("",1,nmsg))%刪除整行

msg = sprintf("%s%0.2f%%","Processed Rate: ",rate);

disp(msg);

nmsg = numel(msg)+1;

pause(0.01)

end

-----------------------------------

對於多重循環,可以簡單地寫成:

-----------------------------------

fprintf("
Total:%d_%d
",NI,NJ);

for I=1:NI

fprintf("%4d_",I);

for J=1:NJ

fprintf("%4d",J);

%你

%要

%做

%的

%事

fprintf(repmat("",1,4))

end

fprintf(repmat("",1,5))

end

-----------------------------------


用wav()函數函數來放音樂。

可以自己編寫正弦函數波形進行播放。

也可以把別的音頻文件存成.wav模式,用wavread讀取,在workspace中存成向量,並提取其採樣頻率fs。

然後用wav(music,fs)來播放即可。

不過要說奇技淫巧的話,那就是你可以以wav(music,1.4*fs)進行播放,把周杰倫變成周婕綸了。


用matlab畫的滑稽(雖然不太像)

初學者,代碼還是很簡單的(勿噴):

x = -10:0.001:10;y = sqrt(100 - x.^2);plot(x,y);hold on;plot(x,-y);hold on;

x = -8:0.001:8;y = sqrt(72 - x.^2);plot(x,-y);hold on;

x = -8:0.001:8;y = -sqrt(81 - x.^2) + 0.9;plot(x,y); hold on;

x = -8:0.001:-2;y = sqrt(13 - (x + 5).^2) - 2;plot(x,y);hold on;

x = -10.5:0.001:-0.5;y = sqrt(28 - (x + 5.5).^2) - 1;plot(x,y);hold on;

x = 2.5:0.001:8.5;y = sqrt(13 - (x - 5.5).^2) - 2;plot(x,y);hold on;

x = 0:0.001:10;y = sqrt(28 - (x - 5).^2) - 1;plot(x,y);hold on;

x = -9.5:0.001:-6.5;y = sqrt(2.25 - (x + 8).^2) + 2;plot(x,y);hold on; plot(x,4 - y);hold on;

x = 1:0.001:4;y = sqrt(2.25 - (x - 2.5).^2) + 2;plot(x,y);hold on; plot(x,4 - y); hold on;

x = -8:0.001:-4;y = 8 - (x + 6).^2.*0.75;plot(x,y);hold on;

x = 4:0.001:8;y = 8 - (x - 6).^2.*0.75;plot(x,y);hold on;

x = 4:0.001:8;y = 7 - (x - 6).^2.* 0.5;plot(x,y);hold on;

x = -8:0.001:-4;y = 7 - (x + 6).^2.* 0.5;plot(x,y);hold on;

轉載註明出處


某天在Lab幹了一天活,到了晚上感覺天昏地暗,就像這樣↓

一陣冷風吹過,一個激靈突然想起來我的perl腳本還沒寫完ヾ(?`Д′?),慌亂之中就對著Matlab終端一頓狂敲Linux命令行,結果……我一定是喝多了!


p圖,很好的


matlab的矩陣操作有優化,for循環運算效率低。盡量用矩陣操作,不用for循環。

m文件執行進入循環,需要強制退出的話,按ctrl+C


mat可以同時開多個窗口。

……………………分割線………………

就是說你可以在一台機上同時打開好幾個mat。

從上大學就開始用mat,別的軟體除了r語言基本不碰。但一直中二的「以為」只能開一個(其實是根本沒意識到)。有次為了同時運行三個程序,搬出三台筆記本。

只是個人經驗,輕噴。


推薦閱讀:

為什麼都2015年了,學校裡面的開發還是用vc6?
樹莓派做集群的意義?
如何評價 MATLAB R2016b ?
c++ 臨時變數問題?
為什麼 Python 現在(2015年)越來越火了?

TAG:編程 | MATLAB | X編程語言有什麼奇技淫巧 |