Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Removing trailing zeros from %f format specification in fprintf

1,017 views
Skip to first unread message

Peter Lessing

unread,
Feb 25, 2016, 1:22:07 PM2/25/16
to
I have been writing a GUI to input data for a second program (old program written in FORTRAN). The FORTRAN program has very strict limitations on its input, so when writing the output file from my GUI I have uses fprintf statements to write floating point numbers in a 10 character width field, left justified. The problem that I have is matlab insists in writing these numbers with 6 digits past the decimal point, including unnecessary trailing zeros. As a result, when the value of the number before the decimal point is around

I do not want the trailing zeros is more than three digits (i.e. > 999). the matlab fprintf statement automatically expands the size of my field width beyond 10 characters to print 6 decimals past the decimal place, messing up the output file format. For example, I want to print the number 138000.0 to a field of no more than 10-character width, but matlab fprintf prints it as:

138000.000000 and auto-expanding the field width to 13 characters despite my using the format specification '%#-10f', which should left-justify in a field width of 10 characters.

This is driving me crazy that you cannot control field width in the fprintf.

I do NOT want to use something like '%#-10.3f' because I may have a precision more than three digits past the decimal point, yet still occupy a 10-character or less width field, with a number such as -0.0199 (which by the way will print as left-justified -0.019900 giving me two redundant trailing zeros I do not want to print).

It is beyond me why matlab makes formatting so problematic. This is a very complicated GUI and I am getting caught up in this detail of writing the output format I want.

Any help would be appreciated.

One thing I tried was writing each number to a string variable using the '%#-10f' format specification, and then passing the resulting string to the function shown below, which uses regular expressions to trim trailing zeros, but for some reason, its not working on some numbers. This function is called within a callback that is activated when I press a button in my GUI which then collects a number of doubles and writes them using sprintf and passing the resulting string to the function below to trim trailing zeros, however the function doesn't always work on the variables passed for some reason.

an example of this technique would be:

strin = sprintf('%#-10.f', var);
strout = stripzeros(strin);
and then I would print strout to the file as:

fprintf(fp1, '%10c', strout);

which I believe would preserve my 10-character field width

I am not sure why the function stripzeros is not working when called within my GUI callback but for some reason it doesn't always work.

Does anyone know of a simpler way to trim unneeded trailing zeros, or is there a format specification flag that will stop matlab from printing these annoying trailing zeros?

Thanks in advance.

function str = stripzeros(strin)
%STRIPZEROS Strip trailing zeros, leaving one digit right of decimal point.
% Remove trailing zeros while leaving at least one digit to the right of
% the decimal place.

% Copyright 2010 The MathWorks, Inc.

str = strin;
n = regexp(str,'\.0*$');
if ~isempty(n)
% There is nothing but zeros to the right of place itself.
% Remove all trailing zeros except for the first one.the decimal place;
% the value in n is the index of the decimal
str(n+2:end) = [];
else
% There is a non-zero digit to the right of the decimal place.
m = regexp(str,'0*$');
if ~isempty(m)
% There are trailing zeros, and the value in m is the index of
% the first trailing zero. Remove them all.
str(m:end) = [];
end
end

dpb

unread,
Feb 25, 2016, 1:52:16 PM2/25/16
to
On 02/25/2016 12:22 PM, Peter Lessing wrote:
...

> It is beyond me why matlab makes formatting so problematic. This is a
> very complicated GUI and I am getting caught up in this detail of
> writing the output format I want.
...

It's C which is causing the grief (or at least the definition which
Matlab uses) for formatted i/o.

I suppose there's no chance of recompiling the Fortran code to make it
more modern and use list-directed input instead of the fixed field widths?

I think you'll have similar problems even if used Fortran formatted i/o
to achieve the results you're asking for; even it will fill a precision
field with trailing zeros (and they're superfluous for the input so not
a problem from that standpoint) although it (Fortran, that is) _will_
not extend the field width but fill with asterisks on output if the
numeric value doesn't fit within the specified format.

I don't know enough regexp to debug the cleanup routine; a brute force
solution might be to fliplr() the string result and find the first
nonzero character and delete up to it, then flip back. Same thing as
search from the end back, of course...

--

Peter Lessing

unread,
Feb 25, 2016, 2:25:10 PM2/25/16
to
"dpb" wrote in message <nanib2$c26$1...@dont-email.me>...
Yes that is part of my problem. I don't know much about regular expressions either. The matlab help on it is so cryptic as to make it incomprehensible. The function is one that I got from a blog on this site and by itself, seems to work at stripping trailing zeros, however when I put the function in my GUI callback, it only worked when there was nothing but zeros after the decimal point, but would do nothing when there were both numbers and trailing zeros after the decimal point.

porting over the FORTRAN is not really an option for me at this time as it is a very large, complex program. All my GUI is doing is taking data input by the user and then writing it out to a file in the structured format required as input by the FORTRAN program.

The GUI itself is fairly complex as there are a large number of values that have to be entered through multiple GUIs. Its the %f format specification that is giving me the issue as there is no flag that allows suppression of trailing zeros, and matlab automatically expanding the field wdith beyond 10 characters.

dpb

unread,
Feb 25, 2016, 3:34:41 PM2/25/16
to
On 02/25/2016 1:25 PM, Peter Lessing wrote:
...

> porting over the FORTRAN is not really an option for me at this time as
> it is a very large, complex program.

Well, was a thought altho I figured likely would be the case the
question needed to be raised.

> ... All my GUI is doing is taking data
> input by the user and then writing it out to a file in the structured
> format required as input by the FORTRAN program.

What about writing that file as it comes and then post-processing it w/
a Fortran filtering program to create the actual input file? That could
be dispatched inside the GUI and the user need never know it would seem.

> The GUI itself is fairly complex as there are a large number of values
> that have to be entered through multiple GUIs. Its the %f format
> specification that is giving me the issue as there is no flag that
> allows suppression of trailing zeros, and matlab automatically expanding
> the field wdith beyond 10 characters.

Again, it's the C i/o library that's the culprit; Matlab is just using
the RTL of the compiler (presumably MS??) to do the actual i/o and
that's what the width field is defined by in C -- "at least", not "maximum".

--

dpb

unread,
Feb 25, 2016, 3:36:51 PM2/25/16
to
On 02/25/2016 1:25 PM, Peter Lessing wrote:
...

> Yes that is part of my problem. I don't know much about regular
> expressions either. The matlab help on it is so cryptic as to make it
> incomprehensible. The function is one that I got from a blog on this
> site and by itself, seems to work at stripping trailing zeros, however
> when I put the function in my GUI callback, it only worked when there
> was nothing but zeros after the decimal point, but would do nothing when
> there were both numbers and trailing zeros after the decimal point.

Oh, one thought...perhaps there's a nonprinting character like a \n or
something in the string representation that's causing the failure?

Seems like if it works for a straight string, the GUI shouldn't matter
on the same input so, ergo, one suspects the input...

Again, just a thought, no data...

--

dpb

unread,
Feb 25, 2016, 4:31:26 PM2/25/16
to
One last thought -- with the idea of the post-processor on your initial
file, you might consider G format instead of explicit F. There you can
specify the number of significant digits you want kept and the internal
logic of the i/o rtl will handle a lot of the issues you're currently
having regarding size of the argument and field with which to express it.

With Fortran input, if the decimal is specifically given in the field,
it will override any format that is used in the READ so while it may not
be the "prettiest" for human consumption, it'll likely work best for
automated input file creation.

I've not tested 'g' much in C; I think, however, it still has the
problem that field width simply does not mean what it does in Fortran so
it likely will still be too wide on occasion.

--

Peter Lessing

unread,
Feb 25, 2016, 5:29:12 PM2/25/16
to
"dpb" wrote in message <nanrli$ioa$1...@dont-email.me>...
I think I solved it. The method I was employing using the function above that stripped trailing zeros was failing because sometimes when printing the number to the string variable that was passed to the 'stripzero' function, there was sometimes a number that did not completely fill the 10 character field, so when it was printed in the string variable left justified, it left one or more blanks on the end of the number field (such as: '0.000000 ' -- this is an example where zero was printed to the string variable with two trailing blanks in the 10-character field). The 'stripzero' function was failing because it expects the last character of the number to be a redundant trailing zero (which would then be stripped). In the case of the blanks on the end, it "fails" because its not a number. As a result, I just got back whatever number I passed the function because of the trailing
blanks. The solution was to use deblank() on the printed string number prior to passing it to the stripzero function. deblank() removes all trailing whitespace at the end of the string, so for example:

Print the number to a string:

str = sprintf('%#-10f', var);

then deblank the string:

str = deblank(str);

and then strip the zeros:

str = stripzeros(str);

or as a one-liner:

str = stripzeros(deblank(sprintf('%#-10f', var)));

deblanking the string prior to passing it to stripzeros took care of the problem.

Thanks for your suggestions.

Steven Lord

unread,
Feb 26, 2016, 10:16:32 AM2/26/16
to


"Peter Lessing" <pete.l...@noaa.gov> wrote in message
news:nankef$oou$1...@newscl01ah.mathworks.com...
In my opinion, that's not the documentation's fault -- regular expressions
are a very powerful tool, but the learning curve (particular for more
complicated expressions) is more of a learning cliff. Even the Wikipedia
regular expression page looks complicated.

https://en.wikipedia.org/wiki/Regular_expression

> The function is one that I got from a blog on this site and by itself,
> seems to work at stripping trailing zeros, however when I put the function
> in my GUI callback, it only worked when there was nothing but zeros after
> the decimal point, but would do nothing when there were both numbers and
> trailing zeros after the decimal point.
> porting over the FORTRAN is not really an option for me at this time as it
> is a very large, complex program. All my GUI is doing is taking data
> input by the user and then writing it out to a file in the structured
> format required as input by the FORTRAN program.
> The GUI itself is fairly complex as there are a large number of values
> that have to be entered through multiple GUIs. Its the %f format
> specification that is giving me the issue as there is no flag that allows
> suppression of trailing zeros, and matlab automatically expanding the
> field wdith beyond 10 characters.

Perhaps another approach, if you want the EXACT Fortran behavior, would be
to create a simple Fortran MEX-file that accepts a number and uses the
Fortran I/O functions to create a string in the exact format you want. That
way instead of trying to adapt how MATLAB formats the string to match how
the Fortran code expects, you would have MATLAB ask _Fortran_ to format the
string the way Fortran expects the string to be formatted. Looking at this
page of MEX examples:

http://www.mathworks.com/help/matlab/matlab_external/table-of-mex-file-source-code-files.html

you could probably combine matsq.F (to pass numeric data from MATLAB to
Fortran) and passstr.F (to pass a string from Fortran to MATLAB) to get you
most of the way there. Glue them together with Fortran code to convert the
number into a string formatted exactly how your other Fortran code expects
it to be formatted.

--
Steve Lord
sl...@mathworks.com
To contact Technical Support use the Contact Us link on
http://www.mathworks.com

Paul Mennen

unread,
Feb 28, 2016, 10:44:11 PM2/28/16
to
"Peter Lessing" <pete.l...@noaa.gov> wrote
> This is driving me crazy that you cannot control field width in the fprintf.

Peter, you are not the first person to be driven to distraction trying to use c style formatting codes, especially in a GUI where the conversion must fit into a fixed spaced field. Wouldn't it be nice if there where a format code that said "just be smart about it and do the best you can while limiting yourself to "n" characters". Of course it should be smart enough to decide when shifting over to exponential notation is going to be an improvement rather than a distraction. The c formatting codes don't get you even close and as you have noticed you can't even limit the field width if the range of input numbers is sufficiently wide. No matter what parameters you apply to either the f,e, or g formats, sooner or later you are going to be quite annoyed at the way matlab formats the number to appear in your GUI. Fortran formatting is somewhat better, but still not quite smart enough to always
do what you want. (Fortran formatting also had "repeat counts" a concept sadly missing from c format conversions).

A decade or so ago I said to myself, enough is enough ... we actually need a DWIM or DWIW formatting code (Do What I Mean/Want) so I designed one for Matlab. Actually I designed four new formatting codes (%V, %W, %v, %w) although the last one (%w) is the one that I usually use for GUIs. This has been available for a long time on the file exchange, although perhaps unfortunately it is included as part of a large package, which is why almost nobody knows about it.

To find the package, just search for "plt" on the file exchange. This package has lots of useful stuff in it, but if all you are interested in is the new DWIW formatting codes, just extract these 3 files from the package:

prin.m (this is a replacement for matlab's sprintf and fprinf functions)
Pftoa.m (called by prin.m - actually implements the new formatting codes)
prin.pdf (this is the most important file, since it explains the whole idea in detail).

Although you could call Pftoa directly, it is usually more concise and consistent to use prin().
And by the way, there is nothing that sprintf() or fprintf() can do that prin() can't do!

Another neat thing about prin() is that it brings back the repeat counts that only us old time fortran programmers miss - but even the younger guys who have never seen a line of fortran will come to appreciate repeat counts once you have them. And finally, prin() adds some functionality relating to the way it handles cell arrays. Once you take advantage of this capability, I trust you will agree that sprintf should have had this functionality from the day the Mathworks added the cell array data structure to the language.

~Paul
0 new messages