Displays the percentage done of a job to the command line interface.
Adam Leadbetter (2021). Percent Done (https://www.mathworks.com/matlabcentral/fileexchange/24099-percent-done), MATLAB Central File Exchange. Retrieved .
I use 'dispstat' function just for this purpose. It can update the previous output which is a missing function of default 'disp'. Very simple to use. It can be downloaded from here:
dispstat('','init'); % One time only initialization
dispstat(sprintf('Begining the process...'),'keepthis','timestamp');
for i = 97:100
%doing some heavy stuff here
11:25:37 Begining the process...
11:25:37 Progress 100%
All the best
Fantastic program. It does exactly what it says it does. Extremely easy to insert into a for loop and get an update on the progress through the for loop in real-time.
I just made a few changes:
1. The first time the program is run, the persistent variable 'lastCall' is empty, and so the "Percentage Complete" line displayed inside previous text I had printed to the workspace. So I just added a catch, which sets lastCall to -1 on the very first run, and that means the first time the function 'perccount' is run, the "Percentage Complete" line is displayed correctly.
2. I modified the last check (which checks whether the progress is complete) from
This means the displayed line ends up showing "Percentage Complete: 100%" rather than "Percentage Complete: 99%", which is untrue - everything has completed properly!
3. A program without good commenting makes it very difficult to use and understand for other programmers. A description of the required variables used by the function at the start of the code helps a huge amount, and Adam, you did this very nicely! But if I want to understand how the program works, then it really helps to have some commenting through the code.
The code I am now running is:
%Reports the percentage of the job done to the screen.
% I is the current iteration between 1 and Imax
% Imax is the maximum number of iterations
% Do not print anything to the screen between calls of this function!
% title - s cmspike/perccount vr - 1.2
% author - bodc/alead date - 2006may16
% Updated 2009May14
% At suggestion of John D'Errico renamed internal variable "max" to
% Also following D'Errico's suggestions the following functionality has
% been added:
% 1. An invocation check - checks that two input arguments are
% lastCall is the last integer percent displayed
% if the number of arguments is 2
if(nargin == 2)
% if this is the first run, make lastCall a value that will get the
% following if loops working from the start.
lastCall = -1;
% if the percentage has increased to the next integer, then the
% displayed percentage will need to be updated
if(lastCall ~= floor(((jj-1)/maxjj) * 100))
% if the progress so far (jj out of maxjj) is not the first
% representation, then backspace the percentage area to prepare for
% the next percentage update.
if(jj ~= 1)
% if the progress so far IS the first time it is displayed, then
% display the "context line" of the percentage.
fprintf(1,'\n\tPercentage complete: ');
% Calculate the percentage done
pc_done = num2str(floor(((jj-1)/maxjj) * 100));
% if the percentage done so far is in the single digit range
% (between 0 and 10), then add a zero before it so the percentage
% displays neatly
if(length(pc_done) == 1)
pc_done(2) = pc_done(1);
pc_done(1) = '0';
lastCall = floor(((jj-1)/maxjj) * 100); % the last int percent displayed
% if this is the last part of the total, then display 100% complete and
% add a few lines of whitespace for neatness
if(jj == maxjj)
error('Error: PERCCOUNT needs two input arguments...');
One final suggestion: Perhaps change the function to percentComplete.m, or percentDone.m, as this makes more sense than perccount.m, but that's entirely up to you!
Fixed the problems I saw. It does what it claims to do. It is faster now too, taking a much smaller chunk of time away from your own computations. Whereas the last time I did this test, it too almost 10 seconds just to do the progress report, this test is down to only about a second.
tic,for i = 1:10000,perccount(i,10000),end,toc
Elapsed time is 1.243821 seconds.
Perccount is not infinitely fast, but waitbar will be just as slow, if not worse. This begs the question of just how slow?
h = waitbar(0,'I''m busy!');
n = 10000;
for i = 1:n
Elapsed time is 124.846332 seconds.
Yes, just 10000 calls to waitbar, with nothing else in the loop, took over 2 minutes!
So, for the person who will have wanted to ask, "Why not just use waitbar?" this is a good reason. All of those calls to update a slider bar take considerable time. Yes, I'll admit that more careful coding, calling waitbar only infrequently in that loop would have been faster. So,
h = waitbar(0,'I''m busy!');
n = 10000;
for i = 1:n
if (rem(i,100) == 0)
Elapsed time is 1.280422 seconds.
So for the person who does not wish to write the extra code to make waitbar function passably, or for the person who would actually prefer to have progress reported in the command line, perccount is a very viable option.
My thanks for fixing this. Well done.
Help is reasonable here. No error checks. (sadly, error checks will just slow this down.) An H1 line.
This works reasonably if you never call it more than 100 times, and if each pass through the loop is lengthy. The fact is, many loop variables will exceed 100. So I tried this:
for i = 1:100000
What you will see is the numbers flickering, so quickly that you cannot read the percentages. Perhaps a better solution is to use a persistent variable, checking to see if there is a reason to update the screen (i.e., the percentage as reported would be different.) Do something like round(100*jj/Imax). If this changes, then and only then do an update to the screen.
Don't forget that calling such a function many thousands or even millions of times may add significant additional time to the running of your code. 0.001 seconds for each call adds up when you make that call 1e6 times. Admittedly, this is a problem with waitbar too. In general, it is probably better to restrict calls to any style of progress report to only a few hundred at most. So a test outside of this code may make some sense. Whenever I put in a waitbar, I generally do exactly that.
Next, I ran a timing test:
tic,for i = 1:10000
Percentage complete: 99%Elapsed time is 9.704124 seconds.
First, see that toc has reported its result on the same line as the progress report. This would be irritating, at least to me. Clean up after yourself!
Next, it too almost 10 seconds (on my admittedly slow CPU) to just call this function 10000 times. So big loops will indeed add a significant amount of time to your code.
Finally, this code takes its second variable with the name "max"! (Even thought the help calls it Imax, the code itself calls the variable max.) While this is in itself not a bug, it is a poor choice. You have superseded the max function. While this code does not try to call max, it is just bad form. Use names for variables that are NOT the names of existing, frequently used, built-in functions. Someone who is reading your code in the future may easily be confused. Worse, suppose you decided to change this code in a way that required you to use the max function itself? A bug waiting to happen.
I do appreciate that all waitbars are time hogs, even so, this seems to be worth about a 3 rating. As always, improvements are encouraged.
Find the treasures in MATLAB Central and discover how the community can help you!Start Hunting!