天天看點

MATLAB仿真總結

MATLAB仿真過程中,編寫MATLAB代碼的時候犯了很多錯誤,做了很多蠢事。記錄下自己犯錯的點點滴滴,并引以為戒。使用MATLAB版本為2014a,以下内容如有不當還請指正。

1. 仿真開始前清理工作區

    工作區存在的變量可能會對腳本運作産生影響,故代碼(腳本)開頭需要添加如下指令

clc;clear all;close all;      

2. 養成良好的變量、函數命名習慣

    MATLAB中有很多内置的常量、函數等。寫代碼的時候不能夠随意命名,以防造成不必要的麻煩。譬如在循環時不應該使用i,j變量,在MATLAB中這多用于表示虛數符号。更多的内容可以參考《MATLAB 程式設計風格指南》。

3. 測試完成的代碼再寫出函數形式

    有時候會把相對獨立、固定的内容寫成一個函數。但往往直接寫成函數後是不利于測試的,即使添加斷點後進入函數内部檢視各變量取值,此時不能夠觀測到函數之外的變量。是以測試好代碼無誤再封裝成函數是必要的。

4. 浮點數的精度

    舉個例子,下面代碼運作結果是什麼呢?

a=10^-17;b=1;
if(a+b==1)
    fprintf('a+b=1');
else
    fprintf('a+b!=1');
end      

    答案應該是輸出 a+b=1,雖然很明顯這是不成立的,但我們要知道MATLAB不是萬能的,其表示的數的精度是有限的。對于精度問題不做具體的讨論,意識到這個問題後,我們必須将理論和時間區分開。

    譬如在做除法的時候,有些變量依理論而言是不為0的,但實際上可能因為運算過程中的精度損失而使得計算結果産生Inf或是NaN,進而導緻程式出現偏差。就拿上述例子來說,運作結果表明a+b-b=0。為避免這些情況的發生,必須對程式做相應的處理。在MATLAB中鍵入

help eps      

      This MATLAB function returns the distance from 1.0 to the next largest double-precision number, that is eps = 2^(-52).

    可以在幫助文檔内閱讀較長的描述,在實際代碼中運用eps防止出現異常。(由其是在具有循環疊代的代碼中更要注意這一點)

5. 寫好注釋,用好釋出功能

    我有個腳本試着釋出了一下,如這裡所示,實際上要好看些。這部分内容可以在幫助-MATLAB-Programming Scripts and Functions-Scripts中找到相關的介紹。個人覺得還是不錯的,注釋是肯定要寫的,既然要寫,為何不好好按照格式寫呢?

    當然,MATLAB提供的功能還是比較簡單的,具體的功能大概也就這些。使用釋出功能後代碼會運作一遍,之後将結果也添加到釋出的文檔中去。

%%文檔标題
% 具體描述
%
%    有格式文本
%    最後修改日期:2015-03-07
%    軟體版本:MATLAB(R) 2014a
%
% *加粗*
%
% # 編号清單
% # 編号清單

%%有标題節
% 

%%
%      

6. 用好幫助,更要看清幫助

    為什麼很多仿真都用MATLAB?因為MATLAB很強大,很全面,可以做好很多事情。了解其強大功能的一個很好的途徑是看其自身的幫助。當然,我想強調的是看清幫助。

    前幾天就犯了個錯誤,sgn是取符号的函數,MATLAB裡面有個函數叫做sign實作了這個功能。然後我就用了,沒有看清sign(0)=0……然而我希望的結果是sign(0)=1。是以在實際使用過程中還是要看清楚才行。

7. 适時儲存運作結果

    有的仿真要跑1天、兩天、很多天,而且往往是可以中斷的。為了防止電腦當機、斷點,适時儲存運作結果是必要的。我們可以讓程式在指令行視窗實時輸出資訊以檢視代碼運作狀态,并利用diary将這些資訊儲存起來。譬如

diary;
fprintf('\n-------------------------------\n');
fprintf('Eb/No = %e \n',Var1);
fprintf('總幀數 = %d, ',Var2);
fprintf('誤幀數 = %d, ',Var3);      

    但我還是覺得建立檔案自由一些,指令行視窗實時輸出資訊的格式還是不太好看。譬如我們可以将運作結果采用表格的形式存儲起來,之後用readtable讀取。

fid = fopen(FILE_NAME,'at+');
fprintf(fid,'日期 %s\n',datestr(now,'yyyymmdd'));
fprintf(fid,'EbN0\t T_Frame\t E_Frames\t E_Bits\t A_IterNums\t BER\t FER\n');
fprintf(fid,'%3.2g\t %5d\t %4d\t ',EbN0_dB(nEbN0),nF,frameError(nEbN0));
fprintf(fid,'%8d\t %8.6g\t ',bitError(nEbN0),iterNumTotal(nEbN0)/nF);
fprintf(fid,'%e\t %e\n',BER(nEbN0),frameError(nEbN0)/nF);  

readtable(FILE_NAME,'HeaderLines',1,'Delimiter','\t')      

    讀取的結果大概是這個樣子,還是很好看的(雖然歪了……),而且可以輕松擷取每列資料。

EbN0    T_Frame    E_Frames    E_Bits    A_IterNums    BER    FER
    ____    _______    ________    ______    __________    ___    ___

    1       1          0           0         27            0      0      

8.待續

……

自由轉載,轉載注明出處(http://www.cnblogs.com/sea-wind/)

姓名标示(BY)-相同方式分享(SA)

下一篇: weinre 簡記

繼續閱讀