Using sprintf to match the results of format

15 views (last 30 days)
John D'Errico
John D'Errico on 20 Jul 2017
Answered: Stephen on 27 Oct 2021
If I read the help for format, it tells me:
format may be used to switch between different output display formats
of all float variables as follows:
format SHORT Scaled fixed point format with 5 digits.
format LONG Scaled fixed point format with 15 digits for double
and 7 digits for single.
format SHORTE Floating point format with 5 digits.
format LONGE Floating point format with 15 digits for double and
7 digits for single.
format SHORTG Best of fixed or floating point format with 5
digits.
format LONGG Best of fixed or floating point format with 15
digits for double and 7 digits for single.
format SHORTENG Engineering format that has at least 5 digits
and a power that is a multiple of three
format LONGENG Engineering format that has exactly 16 significant
digits and a power that is a multiple of three.
I'd like to replicate the behavior of each of these formats, using an appropriate format spec in sprintf. The purpose is for a custom numeric class I was thinking of writing. I'd happily ignore longeng and shorteng, if they were problematic. While I can probably play around with format specs and get something reasonable, someone else is surely much more knowledgable in this matter than me.

Answers (3)

Steven Lord
Steven Lord on 20 Jul 2017
The easiest way to replicate the format specification is to just let MATLAB do it.
oldFormat = get(0, 'Format');
% may want to set up an onCleanup object here to restore the format
% to guard against one of the next few commands throwing an error
% But for demonstration purposes, I assume everything will work fine
% 'replicate' the short format
format short
dataToDisplay = pi;
s = evalc('disp(dataToDisplay)');
% Everything worked fine up to this point, so reset the format
format(oldFormat)
If you're displaying an array, you may also want to get(0, 'FormatSpacing') so you can handle 'loose' and 'compact'.
There are some tools in MATLAB for customizing object display, though I believe those are targeted for helping display groups of properties of an object.
  1 Comment
Ulises Nunez Garzon
Ulises Nunez Garzon on 27 Oct 2021
This is a great answer. To top it off, I would wrap your code to get the desired result in the following way:
function c_str = c_format_short(a)
oldFormat = get(0, 'Format');
dataToDisplay = a;
c_str = evalc('disp(dataToDisplay)');
c_str = strtrim(c_str(2:end-1));
format(oldFormat)
end

Sign in to comment.


dpb
dpb on 20 Jul 2017
As a starting point
>> fnprnt=@(x) fprintf('%.5g\n',x)
fnprnt =
@(x)fprintf('%.5g\n',x)
>> fnprnt(pi)
3.1416
>> fnprnt(pi*1E6)
3.1416e+06
>> format short
>> pi
ans =
3.1416
>> pi*1E6
ans =
3.1416e+06
>>
  3 Comments
Walter Roberson
Walter Roberson on 20 Jul 2017
There is no one format that can replicate the format short output. %13.5g helps (the 13 part deals with the spacing), but format short treats integral values differently than non-integral value, always displaying 0 after the decimal point for non-integral values that %g would not display. 1+eps for example is displayed as 1.0000 but 1 exactly is displayed with no decimal places. %g would display 1+eps with no trailing 0, and the %e and %f formats would always display trailing 0 even for integral values.

Sign in to comment.


Stephen
Stephen on 27 Oct 2021
format short
str = strtrim(formattedDisplayText(pi))
str = "3.1416"
format long E
str = strtrim(formattedDisplayText(pi))
str = "3.141592653589793e+00"

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!