發信人: YFER (你好 2008), 信區: Matlab
标 題: [ZZ]寫給學習 matlab 的新手們
發信站: 紫金飛鴻 (2008年01月18日22:24:51 星期五), 站内信件
轉:本人接觸matlab已經有5年多的時間了,一直想寫點東西,但是之前不知道放在哪裡
才能發揮它的最大作用,直到幾天前碰上了這個論壇(有點像諸葛亮遇見姜維,哈哈)
。
廢話不說,我想借貴論壇寶地,寫一些經驗給使用matlab的新手們,當然了,老大們也
可以看看,不嫌棄我寫得粗糙的話還可以指點一下,先謝過了~~~~
首先我想說的是,matlab跟其他語言不一樣(我用的比較多的程式設計語言,除了matlab就
應該是c或c++了,VB和Delphi也接觸過,我想版面(matlab版)大部分人也差不多),
如果你抱着“把其他語言的思想運用在matlab裡面”的話,那麼我想,即使程式運作不
出錯,也很難把握matlab的精髓,也就很難發揮matlab的作用了。是以,如果你是希望
掌握一門語言、一個工具,使它更有效為你服務的話,那麼,希望本文對你有所幫助,
請精讀;如果你是希望matlab作為VC的附屬品,即你不想在matlab上面花太多功夫,隻
純粹想用matlab來完成VC做不了或很難做成的任務的話,那麼,本文你也應該至少浏覽
一下。
Matlab是一個基于矩陣運算的軟體,這恐怕是衆所周知的事情了,但是,真正在運用的
時候(就是在程式設計的時候),許多人(特别是初學者)往往沒有注意到這個問題,是以
,for循環(包括while循環)滿天飛…………..這不僅是暴殄天物(沒有發揮matlab所
長),還浪費了你寶貴的時間。對此,版友MVH在他的“MATLAB 小技巧”一文中也有所
涉及,雷同的東西我也就不重複了,matlab的“幫助”裡面也有相關的訓示。我這裡想
說的一點是,初學者往往在初始化矩陣的時候注意到這個問題,懂得了使用矩陣而不是
循環來指派,但是,在其他環節上,就很容易疏忽,或者說,仍然沒有擺脫C++的思想
。舉個例子吧,下面的代碼是我的一個師弟寫的,我想他接觸matlab也有2、3年時間了
(在此說明一下,接觸2、3年并不是表示每天都會跟matlab打交道,我本人也不是,隻
是在一年某幾個時間段裡面連續使用),但是仍然會出現類似的問題:
J = 0;
lt = size(imf1,2);
for (i = 1:lt)
if (abs(imf1(i)) > 1)
J = 1;
break
end
end
上面的代碼實作了一個目的――檢查信号imf1(一個向量)是否存在絕對值大于1的點,
這顯然是基于C++的思想寫出來的。如果在matlab下面,其實用兩個語句就足夠了(當
然,可以合并為一個):
q = find(imf1>1);
J = ~isempty(q);
這樣的修改帶來的好處是很可觀的。
又如:
for j = 1:num
imf1(start1+j) = 2*li1(j+1) - imf1(start1+j);
end
這是一個對稱翻折的問題,它完全可以用以下這個語句簡潔表示:
imf1(start1+1:start1+num) = 2*li1(2:num+1) - imf1(start1+1:start1+num);
是以,如果是新手,可以先用循環(基于C++的思想)來編寫代碼,然後看看能否用ma
tlab的語言(基于矩陣的思想)來改進。當然,這樣做的前提是你對matlab提供的一些
函數比較熟悉才行,這些函數在matlab的“幫助”那裡搜尋“Functions Used in
Vectorizing”就可以找到一些,其他的也可以找相關的書籍(沒找到?不可能,電子版
總可以下載下傳到的)
對提高matlab程式設計能力的方法,我想主要有以下三個:
1. 查help
2. 多上上論壇,搜尋文章、發文章問人
3. 閱讀别人、特别是牛人的程式
當然了,正如所有的程式語言一樣,“3分課本7分上機”,一定要動手才行,不能光看
。多想、多思考、多嘗試,才是正路。以下技巧就是平日動手程式設計、閱讀别人的文章後
整理出來的(不斷添加中):
1. matlab的運算是基于矩陣的,但是也提供了對應元素的運算,即在運算符前面加上“
點”。例如:
>> a = [1,2;3,4]
a =
1 2
3 4
>> b = [-1,-2;-3,0]
b =
-1 -2
-3 0
>> a * b
ans =
-7 -2
-15 -6
>> a .* b
ans =
-1 -4
-9 0
也就是說,沒有加“點”的運算是對整個矩陣而言的,稱為矩陣運算(整體運算),而
加了“點”的運算是對每個元素而言的,稱為點運算(局部運算)。另外,一般情況下
,matlab作點運算(了解為左右兩個對象(矩陣)的對應元素參與該運算)時,兩個矩
陣的維數和長度都要求是同大小的,且此時要在運算法前面添加“點”,但是在某些情
況下該“點”可以省略,例如一個标量a和一個向量b(或者矩陣)相加、相減、相乘、b
/a時都可以不需要加點,表示b中每個元素都和a進行運算(即點運算的效果)
2. 強烈建議大家在命名自己的函數名(更加準确應該說m檔案名)時,在名稱前面加上
my 等個人專用辨別,即假如你要把你的函數命名為conv,則最好寫成 myConv,否則容
易與matlab自帶的函數(m檔案)名字重複而導緻“Attempt to execute SCRIPT conv
as a function”的錯誤!當你碰到這個錯誤時,可以在指令視窗中輸入 which conv
all 來看看到底有否重複命名了該函數,有的話,建議把自己命名的檔案改名,保留
matlab 自帶的檔案。此外,命名檔案名時,必須符合辨別符的規範,即不能以數字開頭
等等,否則會出現莫名其妙的錯誤!
3. 條件判斷中,y==0, a-b==0這類語句應該盡量減少使用,除非你可以保證y、a、b在
整個計算過程中是整數,否則兩個浮點數相減、或者一個浮點數不可能完全等于0
4. 循環變量遞減時必須顯式給出步長,即 i = 5:-1:-5 (假設步長為-1),如果遞增
時且步長為1,則可以省略,簡寫作 i = -5:5
5. 在引号環境下的語句中,如果需要使用單引号,則要寫成兩個單引号的形式,不能用
一個雙引号代替!例如:
...'callback','[imp,Fs,bits]=wavread(''temp.wav'');' 檔案名 temp.wav 外面的
是兩個單引号
6. 如果你編寫的函數帶有輸入參數(例如 x ),則跟其他語言一樣,這隻是形式參數
,是以不能通過直接運作該函數(或者m檔案)來測試,這樣會出現 ??? Input
argument "x" is undefined. 的錯誤。一定要從其他地方(如指令視窗或者其他函數對
其調用)來傳遞真實值,此時 x 才是實際參數。如果你有C語言的程式設計經驗,指令視窗
就相當于main函數;如果沒有,以下是舉例:
myPlus.m:
[Copy to clipboard] [ - ]
CODE:
function d = myPlus(a,b)
d = a + b;
指令視窗:
[Copy to clipboard] [ - ]
CODE:
>> x = 2;
>> y = 5;
>> z = myPlus(x,y)
此外,和每一種程式設計語言一樣,所有定義的變量都有一定的作用域。雖然matlab 宣稱變
量不需要定義即可以直接使用,但是,事實上任何程式設計語言的變量都需要先定義才能使
用,是以 matlab 也不例外(看來真的是“ matlab 宣稱變量不需要定義”惹的禍),
隻不過所不同的是并非使用 int x 這種方式來定義,而是使用一個簡單的指派語句包含
定義+初始化。是以,如果直接使用未定義的變量(最常用的是在“=”右邊首次出現)
,則會出現“Undefined function or variable” 的錯誤!例如:
[Copy to clipboard] [ - ]
CODE:
function y = myTest(x)
z = x * 2;
y = t + z;
則運作時 matlab 會報錯:Undefined function or variable t !此時當實際參數傳遞
給輸入變量 x 後, x、z 就被定義了,但是 t 卻沒有。
是以,強烈建議在使用變量之前(特别是循環中使用數組),先預配置設定空間,這樣容易
減少很多莫名其妙的錯誤,具體做法參見以下圖檔:
preallocate.bmp (222.48 KB)
2007-5-18 10:55
7. 如何調試程式:編好程式(沒有文法錯誤),設定斷點(m檔案編輯視窗中菜單
Debug 有 Set/Clear breakpoint),運作程式(菜單 Debug 有 Run 或 Save & Run)
,此時 matlab 會停在斷點處,各變量的值可以通過滑鼠停留在變量名上觀察到,或者
在指令視窗中敲入變量名後得到
8. 對于matlab自帶函數(指令)的問題,請多利用matlab的幫助功能。即在指令視窗中
輸入: help eval 或者 doc eval。更多的幫助指令請參閱以下連結的文章:[轉帖]MAT
LAB中的幫助指令
9. 對于 mat 檔案的讀取,由于存放的是結構體數組,是以調用 A = load('*.mat') 後
,得到的 A 并非原始資料,而是一個結構體,此時需要使用".域名" 才能正确得到資料
,例如:
[Copy to clipboard] [ - ]
CODE:
A =load('*.mat');
後得到:
A =
Signal: [85x7794x64 single]
TargetChar: [1x85 char]
Flashing: [85x7794 single]
StimulusCode: [85x7794 single]
StimulusType: [85x7794 single]
則用:
[Copy to clipboard] [ - ]
CODE:
B = fieldnames(A);
可得到各結構體的域名。
如果要獲得各域中(下以 Signal 為例)的資料,必須用:
[Copy to clipboard] [ - ]
CODE:
S = A.(B{1});
此外,不建議使用 load *; 這種方式讀取 mat 檔案(讀取 dat 等其他格式的檔案也是
類似),因為此時讀取後的變量名是存儲時設定的,假若檔案并非您本人存儲,則無法
獲悉這個變量名,通過這種方式是無法在讀取時候指定資料存放在哪個變量中的,這樣
将會導緻下文不知道使用哪個變量名,甚至會導緻出錯!是以,強烈建議采用A =
load('*.mat'); 方式進行讀取,當然了,如果檔案是您本人存儲的,則用前面的方式比
較簡便,這另當别論。下面以 dat 檔案作為例子說明:
clear all
>> a = magic(4); b = ones(2, 4) * -5.7; c = [8 6 4 2];
>> save -ascii 1_data.dat
>> load 1_data.dat
因為這種方式的讀取是把資料預設存放在以“不含字尾的檔案名”命名的變量中(這裡
為 1_data),但是由于 1_data 不是合法的辨別符,是以 matlab 自動改成 X1_data(
不同版本的matlab可能不同),即讀取出來的資料事實上是存放在 X1_data 變量中。如
果使用 m 檔案方式程式設計(即 load 1_data.dat 後有分号),則這個變量名根本不會顯
示出來,也就是說,對它的改名你是毫不知情的,這時候下文繼續使用 1_data 的話,
就會産生錯誤。
10. matlab 對中文的檔案路徑(不光是檔案名)不太支援,特别是 6.5 版本。
11. 函數不能在指令視窗中定義,隻能在 m 檔案中定義。否則出現: ??? Error:
Function definitions are not permitted at the prompt or in scripts. 的錯誤!
最後,整理一下常用的快捷鍵(用【】表示)或指令:
1. 在指令視窗(Command Window)中:
1) 【上、下鍵】――切換到之前、之後的指令,可以重複按多次來達到你想要的指令
2) clc――清除指令視窗顯示的語句,此指令并不清空目前工作區的變量,僅僅是把屏
幕上顯示出來的語句清除掉
3) clear――這個才是清空目前工作區的變量指令,常用語句clear all來完成
4) 【Tab】鍵――(轉自版友心燈)在[email protected]看到的:在command視窗,輸
入一個指令的前幾個字元,然後按tab鍵,會彈出前面含這幾個字元的所有指令,找到你
要的指令,回車,就可以自動完成。目前讨論結果是:matlab6.5版本中,如果候選指令
超過100個,則不顯示。而在matlab7以後版本中,則沒有這個限制,均可正常提示
5) 【Ctrl+C】(或【Ctrl+Break】)――(轉自版友yangjin_ren)在matlab程式運作
過程中,可能由于程式編寫的失誤,導緻程式不停的運作,在指令視窗輸入“Ctrl+C”
可以将運作的程式停下來,而不需要将整個Matlab程式關掉。不過進行此操作的前提是
能夠激活切換到指令視窗才行,呵呵。
2. 在編輯器(Editor)中:
1) 【Tab】(或【Ctrl+]】)――增加縮進(對多行有效)
2) 【Ctrl+[】--減少縮進(對多行有效)
3) 【Ctrl+I】--自動縮進(即自動排版,對多行有效)
4) 【Ctrl+R】――注釋(對多行有效)
5) 【Ctrl+T】――去掉注釋(對多行有效)
6) 【Ctrl+B】――括号配對檢查(對版本6.5有效,但版本7.0以上無效,matlab把這項
功能自動內建到編輯器裡面了,即在m檔案編輯視窗中會自動進行括号配對檢查,并在窗
口右側有紅橙綠三燈提示,具體請參考以下文章:http://www.simwe.com/forum/thread
-746722-1-4.html )
7) 【F12】――設定或取消斷點
8) 【F5】――運作程式
其餘的例如在Debug狀态下的快捷鍵就不多說了,自己看菜單Debug吧
累了, 有時間再寫吧。希望大家多交流~~~~~~
Coming: (以下東西都是一年前做的了,不知道能否記起,呵呵)——已經全部完成
1) 關于神經網絡的――調用matlab的nntool指令後的使用問題(我做的時候沒有看過其
他書籍或資料,是自己閉門造車的結果,如果寫之前發現其他書籍有相關介紹的話就不
寫了)
2) 關于外部接口的――matlab與C++Builder的接口,想詳細介紹如何利用matcom
4.5在C++Builder中調用matlab的代碼以及matcom的一些技巧。由于我不是搞項目開發的
(搞科研、搞課題的),是以對VC不熟悉,大學的時候學過一點,不過我想對于搞科研
來說C++Builder就足夠了,免去很多麻煩,Builder在界面設計和資料庫連接配接上面(我
隻接觸過這兩方面)還是做得不錯的。同樣,如果發現其他書籍上有類似的東西就不寫
了
3) GUI方面也寫寫吧,隻是一點點心得或者體會,呵呵,這個相對簡單些,篇幅相對要
少些。