1

The field width parameter of sprintf and fprintf (e.g., "n" in "sprintf('%nf',1234)") specifies the minimum width of the field. This means that shorter numbers will be padded but longer numbers will be allowed to extend beyond the specified field width when this is necessary to maintain the specified precision. I am looking for a way to specify the maximum field width such that width supersedes precision.

For example, I would want 1234.56, 1234.56789, and 1.2345 to have the width of 8 characters (including the decimal) and therefore print as 1234.560, 1234.567, and 1.234500, respectively.

Here is a similar question, but without a MATLAB-specific solution Specifying maximum printf field width for numbers (truncating if necessary)?

I feel like someone has to have encountered this problem before, but I was unable to locate anything relevant. Please provide a link if a similar question exists. Thanks

vtag
  • 13
  • 2

2 Answers2

2

You can use floor(log10()) to determine how many non floating digits you have:

X    = [1234.56, 1234.56789, 1.2345]
n    = 8 % number of total digits.
% We create an array of string containing the format: 
%[ '%.4f\n'
%  '%.4f\n'
%  '%.7f\n' ]
form = strcat('%.',num2str(n-1-floor(real(log10(X))).'),'f\n')
% We concatenate this array into one single string and we print the result:
fprintf(reshape(form.',1,[]),X) 

Or you can use a for loop (using the same logic):

for x = X
    form = strcat('%.',num2str(7-floor(real(log10(x)))),'f\n');
    fprintf(form,x)
end

And we obtain:

1234.5600
1234.5679
1.2345000

Edit:

I use floor(log10()) instead of ceil(log10()) so the code won't fail if a number is part of the set 10^n (1,10,100...).

And now this snippet can deal with negative floating number since I only take the real part of the log10 output.

obchardon
  • 10,614
  • 1
  • 17
  • 33
  • Thanks for the workaround! One feature of fprintf that I like, however, is the ability to specify a structure for each row without knowing how many instances I will actually need. Is there a way to have the same level of flexibility with your solution? For example, fprintf(fid,'%.8f%.8f%.8f%.8f\n,X) would print the contents of the array X, four to a row, for as many rows as are necessary (including partial rows). But your approach requires each element of X to be evaluated individually. Is there a modification that could be made to preserve my batch formatting? – vtag Jun 09 '20 at 20:39
0

if you don't mind truncating instead of rounding the hidden digits, try

S = num2str( X(:), '%-10.9f');  % creates a left-justified character-array
fprintf( '%s\n', string( S(:,1:7) ) )

(X would need to be checked for values too big.)