写在前面

在编写Matlab程序的过程中,有时候我们希望将比较关键的一些变量或者是经过一定计算得到的变量显示出来,有时候我们希望在进行较长时间的for循环的时候将进度条显示出来,虽然这些功能并不会影响我们程序整体运行,甚至可以说可有可无,但增加了这些程序后产生的视觉效果可能会使我们对程序运行结果有一个大概的了解。

下面我就以上两个方面进行一个简单的介绍:

显示输出函数:

disp语法

disp(['my test=',num2str(x),'%']);

disp函数类似于C语言中的print函数,可以同时输出字符串和数字(使用num2str函数转换为字符串或字符向量)。

因此我们可以采用disp函数和num2str函数将想要知道的变量显示在Matlab的命令行窗口。

example

% 显示数字
A = [15, 150];
disp(A);
% 显示字符串
S = 'Hello World.';
disp(S);
% 显示超链接
X = '<a href = "https://www.mathworks.com">MathWorks Web Site</a>';
disp(X);

sprintf

st = sprintf('my test=%a.bd',x);  % 有符号整型
st = sprintf('my test=%a.be',x); % 定点浮点型
st = sprintf('my test=%a.bf',x); % 指数浮点型
st = sprintf('my test=%a.bg',x); % 紧凑浮点型

sprintf函数可以将数据格式转换为字符串或字符向量,相比于num2str函数,它可以指定格式化操作符(格式化操作符以%开头,以转换字符结尾,可以在%和转换字符之间指定标识符、标志、字段宽度、精度和子类型操作符)格式化数据,因此使用起来更加灵活。

其中,%为数据格式符,因此%到d/e/f/g之间的字符是不显示的,它只是指出数据的格式,同时a.b表示数字的长度为a位,小数点后b位。

disp+sprintf

disp(['my test=',sprintf('%a.bf',x),'%']);

通过以上分析,采用disp函数和sprintf函数可以帮助我们更加方便的显示数据。

fprintf语法一

fprintf(fileID,formatSpec,A1,...,An);

fprintf函数按列顺序将formatSpec应用于数组A1,…,An的所有元素,并将数据写入到一个文本文件。

example

x = 0:0.1:1;
A = [x;exp(x)];

fileID = fopen('exp.txt','w');
fprintf(fileID,'%6s %12s\n','x','exp(x)');
fprintf(fileID,'%6.2f %12.8f\n',A);
flose(fileID);
% 通过type exp.txt查看

fprintf语法二

fprintf(formatSpec,A1,...,An);

fprintf函数设置数据的格式并在屏幕上显示结果。

example

A1 = [9.9, 9900];
A2 = [8.8, 7.7 ; 8800, 7700];
formatSpec = 'X is %4.2f meters or %8.2f mm\n';
fprintf(formatSpec,A1,A2)

fprintf语法三

nbytes = fprintf(__);

使用前述语法中的任意输入参数返回fprintf所写入的字节数

example

A = magic(4);
fileID = fopen('myfile.txt','w');
nbytes = fprintf(fileID,'%5d %5d %5d %5d\n',A);
flose(fileID);

example

% 显示超链接
url = 'https://www.mathworks.com'
sitename = 'MathWorks Web Site'
fprintf('<a href = "%s">%s</a>\n',url,sitename);

转换字符:

值类型 转换 详细信息
有符号整型 %d 以10为基数
%i
无符号整型 %u 以10为基数
%o 以8为基数-八进制
%x 以16为基数-十六进制,小写字母a-f
%X 以16为基数-十六进制,大写字母A-F
浮点数 %f 定点记数法,使用精度操作符指定小数点后的位数
%e 指数记数法,小写字母e
%E 指数记数法,大写字母E
%g 更紧凑的%e或%f,不带尾随零
%G 更紧凑的%E或%f,不带尾随零
字符或字符串 %c 单个字符
%s 字符向量或字符串数组

标识符

处理函数输入参数的顺序,使用语法为:n$,其中n代表函数调用中其他输入参数的位置。

example

fprintf('%3$s %2$s %1$s %2$s','A','B','C');
% 输出为:C B A B

标志

'-' 左对齐
示例:%-5.2f
示例:%-10s
'+' 始终为任何数值输出符号字符
示例:%+5.2f
右对齐文本
示例:%+10s
' ' 在值之前插入空格
示例:% 5.2f
'0' 在值之前补零以填充字段宽度
示例:%05.2f
'#' 修改选定的数值转换:
对于%o、%x、%X,将输出0、0x、OX前缀
对于%f、%e、%E,即使精度为零也将输出小数点
对于%g、%G,不删除尾随零或小数点
示例:#5.0f

显示进度条函数:

进度条显示包含以下四个部分:

窗口打开部分

wait_title = waitbar(0,'Program Initializing ...');  

数据更新部分

Display_Data = num2str(roundn(i/N*100,-1));
Display_Str = ['Computation Progress ... ',Display_Data,'%'];

动态显示部分

waitbar(i/N,wait_title,Display_Str) 

窗口关闭部分

close(wait_title);

通过以上四个部分与for循环的结合,我们可以得到基本的进度条函数:

基本进度条函数

wait_title = waitbar(0,'Program Initializing ...');  
pause(1);
for i = 1:N

%%%%%%%
%代码块
%%%%%%%

pause(0.001);
Display_Data = num2str(roundn(i/N*100,-1));
Display_Str = ['Computation Progress ... ',Display_Data,'%'];
waitbar(i/N,wait_title,Display_Str)

end
pause(1);
close(wait_title);

一般情况下,pause(a)表示程序暂停a秒后继续执行,若pause()无参数,则表示程序暂停,按任意键程序继续执行。

执行效果如下:

randn

如果我们想知道程序在这个循环下运行了多长时间,那么我们在基本进度条函数下添加计时子函数,就得到了计时进度条函数:

计时进度条函数

tic
wait_title = waitbar(0,'Program Initializing ...');
pause(1);
for i = 1:N

%%%%%%%
%代码块
%%%%%%%

pause(0.001);
Time_Trans = Time_Transform(toc);
Time_Disp = Time_Display(Time_Trans);
Display_Data = num2str(roundn(i/N*100,-1));
Display_Str = ['Computation Progress ... ',Display_Data,'%',' --- ',...
'Using Time: ',Time_Disp];
waitbar(i/N,wait_title,Display_Str)

end
pause(1);
close(wait_title);
toc

时间转换函数

function y = Time_Transform(u)
Time_in = u(1);
Hours = fix(Time_in/3600);
Minutes = fix((Time_in-Hours*3600)/60);
Seconds = fix(Time_in-Hours*3600-Minutes*60);
Time_out = [Hours Minutes Seconds];
y = Time_out;
end

时间显示函数

function y = Time_Display(u)
Hours = u(1);
Minutes = u(2);
Seconds = u(3);

if Hours == 0
if Minutes == 0
Time_out = [num2str(Seconds),'','s'];
else
Time_out = [num2str(Minutes),'','m','',...
num2str(Seconds),'','s'];
end
else
Time_out = [num2str( Hours),'','h','',...
num2str(Minutes),'','m','',...
num2str(Seconds),'','s'];
end
y = Time_out;
end

执行效果如下:

randn
我们有时候后不可避免地需要进行大容量数据处理、多仿真结果对比以及复杂算法执行过程监测等,通常而言,数据处理需要耗时几分钟至数小时不等,我们可以采用waitbar函数预测程序执行进度及剩余时间,并希望借此提高我们的工作效率。

本文作者水平有限,如有错误,恳请批评指正!