Matlab sprintf formatting - matlab

EDIT: I've reworded the question to be clearer.
Does anyone know a clever way to get sprintf to print "%.6f with trailing zeros elminated"? This is what I'm looking for:
sprintf('%somemagic ', [12345678 123.45])
ans = 1234578 123.45
where %somemagic is some magical specifier. None of the formats seem to work.
% no trailing zeros, but scientific for big nums
sprintf('%g ', [12345678 123.45])
ans = 1.23457e+007 123.45
% not approp for floats
sprintf('%d ', [12345678 123.45])
ans = 12345678 1.234500e+002
% trailing zeros
sprintf('%f ', [12345678 123.45])
ans = 12345678.000000 123.450000
% cannot specify sig figs after decimal (combo of gnovice's approaches)
mat = [12345678 123.45 123.456789012345];
for j = 1:length(mat)
fprintf('%s ', strrep(num2str(mat(j),20), ' ', ''));
end
I don't think there is a way to do it other than looping through each element and changing the specifier based off of mod(x,1)==0 or using regexp to remove trailing zeros. But you never know, the crowd is more clever than I.
My actual application is to print out the array elements in an html table. This is my current clunky solution:
for j = 1:length(mat)
if mod(mat(j),1) == 0
fprintf('<td>%d</td>', mat(j));
else
fprintf('<td>%g</td>', mat(j));
end
end

EDIT: Updated to address the edited question...
I don't think there's any way to do it with a particular format string for SPRINTF, but you could instead try this non-loop approach using the functions NUM2STR and REGEXPREP:
>> mat = [12345678 123.45 123.456789012345]; %# Sample data
>> str = num2str(mat,'<td>%.6f</td>'); %# Create the string
>> str = regexprep(str,{'\.?0+<','\s'},{'<',''}); %# Remove trailing zeroes
%# and whitespace
>> fprintf(str); %# Output the string
<td>12345678</td><td>123.45</td><td>123.456789</td> %# Output

The problem is that you're mixing an int with a float in an array. Matlab doesn't like that so it will convert your int to a float so that all elements in the array are of the same type. Look at doc sprintf: you're now forced to use %f, %e or %g on floats
Although I admit I like the STRREP method above (or below)

Related

Issues printing a character string in Matlab

I'm new to MATLAB and I'm having problems printing a character array to a file. I only get the first character printed out. I read lines from a file and build an matrix of matrices. One matrix is an array of character vectors. Here's how I read the data
tline = fgetl(iin);
t_current = tline(9:34);
...
data.t = [data.t; t_current];
Then later I do this:
npts = length(data.t);
fid1 = fopen(fname, 'w');
fprintf(fid1, 'Day Rank\n');
fprintf(fid1, '------- -------\n');
for k = 1:npts
time_str = data.t(k);
fprintf(fid1, '%s %f3\n',time_str, data.rank(k));
end
fclose(fid1);
data.t is <10082,26 char> and looks something like this:
val =
2015-07-16T03:28:36.410305
2015-07-16T03:29:00.000000
...
All I get with the fprintf is a '2'. I tried to use convertCharsToStrings but that failed with an error message: Undefined function 'convertCharsToStrings' for input arguments of type
'char'.
This must be something simple I'm missing.
Thanks,
-Mike
Since "data.t is <10082,26 char>", try this:
...
for k = 1:npts
time_str = data.t(k, :);
...
If you do not use the , :, Matlab will use linear indexing for the matrix as opposed to subscripts.
It turns out I needed to use a different format for getting the time string:
time_str=data.t(k,1:end)

In Matlab, how to specify number of digits in the exponent using formatSpec formatting operator?

I'm writing data to an output text file using the fprintf command in Matlab. How to write a number to the output file, for instance, 1.12345678e-001, with three digits in the exponent?
formatSpec = '%1.8e\n';
gives 1.12345678e-01, not the desired result!
There's a similar question here
https://se.mathworks.com/matlabcentral/answers/100772-how-do-i-use-fprintf-to-write-numbers-in-exponential-notation-of-variable-exponent-digits-on-a-windo
But following the instructions given there didn't solve the problem!
You can use this non-regex method:
num = 0.112345678
pow = floor(log10(abs(num)));
sprintf('%.8fe%+.3d', num/10^pow, pow)
ans =
1.12345678e-001
For multiple inputs use this:
num= [.123 .456 .789];
pow = floor(log10(abs(num)));
sprintf('%.8fe%+.3d ', [num./10.^pow; pow])
Not sure if this falls under the category of solution or work-around, but here it goes:
x = .123e25; % example number
formatSpec = '%1.8e\n'; % format specification
s = sprintf(formatSpec, x); % "normal" sprintf
pat = '(?<=e)[+-]\d+'; % regex pattern to detect exponent
s = regexprep(s, pat, sprintf('%+04i', str2double(regexp(s, pat ,'match')))); % zero-pad
It uses regular expressions to identify the exponent substring and replace it with the exponent zero-padded to three digits. Positive exponents include a plus sign, as with fprintf.
This isn't the cleanest answer but you could do something like this. Basic steps are write as is, get the exponent with a regexp, re-write that portion, and replace.
formatSpec = '%1.8e'
tempStr = sprintf(formatSpec,1.12345678e-1);
oldExp = regexp(tempStr,'e[+-]([0-9]+)$','tokens');
newExp = num2str(str2double(oldExp{1}{1}),'%03d');
fixedStr = regexprep(tempStr,[oldExp{1}{1} '$'],newExp)
This outputs:
fixedStr =
1.12345678e-001

Matlab num2str (A, format) function component-wise?

I have
a=[0.221354766 315.806415];
I want sth like (same fieldwidth)
0.2214 315.8064
I tried
b=num2str(a)
% b =
% 0.2213548 315.8064
c=num2str(a,'%8.4f')
% c =
% 0.2214315.8064
d=num2str(a,'%8.7g')
%d =
%0.2213548 315.8064
Any suggestion? Tks
If I understand you correctly, you want the same number of decimal places? If this is the case, just leave off the first number in your format string:
num2str([0.221354766 315.806415],'%.4f ')
ans =
'0.2214 315.8064'
If you want to store these values as strings, then by all means use num2str(a, '%.4f'). It seems odd to take a numerical martrix and store all of the values as strings though, to just round the result use round
m = round([0.221354766 315.806415], 4)
>> m = [0.2214, 315.8064]

displaying a vector in MATLAB using sprintf

I have a vector that looks like:
x =
4.250000000000000
2.719000000000051
5.953000000000088
2.656999999999925
I want to create a string that looks like:
'4.25, 2.72, 5.95, 2.67'
Maybe, I can do something like
disp(sprintf('% 4.2f, % 4.2f, % 4.2f, % 4.2f,', x));
Is there a good way to write those four % 4.2f without actually writing four times so that it can match the length of x?
As suggested by dpwe sprintf support vectorization by default thus
s = sprintf( '%.2f, ', x );
will result with
s =
4.25, 2.72, 5.95, 2.66,
you can remove the trailing comma simply by
s=s(1:end-2)
s =
4.25, 2.72, 5.95, 2.66

Read a text file into matlab

I have a txt file containing multiple questions, and an answer (True / False) like this
A ball is squared. F
My computer is slow. T
etc.
I want to make a function [Q,A] = load.test(filename) where
Q = A cell array containing N strings.
A = A logical vector of N elements.
I have tried different ways, but none seem to work.
[Q,A] = textread(filename,'%s %s');
This output here is the closest I've come:
'A'
'is'
'F'
'My'
'is'
'T'
what do I need to do ?
In case you have more than one . per sentence, the solution of Silas won't work. Also you loose the dot that way. You can also do it as follows:
fid = fopen('questions.txt');
data = textscan(fid, '%s','delimiter','\n')
fclose(fid);
Q = cellfun(#(x) x(1:end-2), data{1}, 'uni',0);
A = cellfun(#(x) x(end), data{1}, 'uni',0);
Alternatively use:
A = cellfun(#(x) x(end) == 'T',data{1});
to get the desired logical vector.
For a text file of content:
The globe is a disk. F
42 is the answer to everything. T
you get
Q{1} = The globe is a disk.
Q{2} = 42 is the answer to everything.
A =
0
1
According to the documentation you should use textscan instead of textread
If you know that the strings are separated by a '.' or another specific delimiter you can do
parsed = textscan(file, '%s %s', 'delimiter', '.');