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.待續

……


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM