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

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]

Related

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

Most efficient way to store numbers as strings inside a table

I want to store efficiently some numbers as strings (with different lengths) into a table. This is my code:
% Table with numbers
n = 5;
m = 5;
T_numb = array2table((rand(n,m)));
% I create a table with empty cells (to store strings)
T_string = array2table(cell(n,m));
for i = 1:height(T_numb)
for ii = 1:width(T_numb)
T_string{i,ii} = cellstr(num2str(T_numb{i,ii}, '%.2f'));
end
end
What could I do to improve it? Thank you.
I don't have access to the function cell2table right now, but using the undocumented function sprintfc might work well here (check here for details).
For instance:
%// 2D array
a = magic(5)
b = sprintfc('%0.2f',a)
generates a cell array like this:
b =
'17.00' '24.00' '1.00' '8.00' '15.00'
'23.00' '5.00' '7.00' '14.00' '16.00'
'4.00' '6.00' '13.00' '20.00' '22.00'
'10.00' '12.00' '19.00' '21.00' '3.00'
'11.00' '18.00' '25.00' '2.00' '9.00'
which you can convert to a table using cell2table.
So in 1 line:
YourTable = cell2table(sprintfc('%0.2f',a))
This seems to be quite fast -
T_string = cell2table(reshape(strtrim(cellstr(num2str(A(:),'%.2f'))),size(A)))
Or with regexprep to replace strtrim -
cell2table(reshape(regexprep(cellstr(num2str(A(:),'%.2f')),'\s*',''),size(A)))
Here, A is the 2D input numeric array.

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

How can I view all elements of a structure of arrays without writing a FOR-loop?

I am interested in seeing all the elements in the :
result(:,:).randMin(1:4,2:end)
in which the result(a=1:24, d=1:5).
In general is it possible to access them without a loop and cat ?
You cannot use the [] trick with multi-level indexing, but if all of randMin are 128 x 11 arrays:
out = [result(1:24,1:5).randMin];
out = reshape(out,[128 11, 24, 5]);
out = out(1:4,2:end,:,:);
Final result has size of 4 x 10 x 24 x 5 where the first two are your randMin(1:4,2:end), and last two dimensions are your a and d respectively.
It looks like you are looking for getfield:
getfield( result, {1:24, 1:5}, 'randMin', {1:4, 2:end} );
I'm a bit rusty with this command and you might need to play with it a bit to make it work.
Read its manual and good luck!
I don't think it is possible because randMin could be something else for every field in result. result(1,1).randMin could be a matrix, result(1,2).randMin could be a vector, result(2,1).randMin could be 4-dimensional...you see where I'm going with this.
So there is no way of knowing the dimensions or the size of each result's randMin without looping through all fields in result. If there is a function that does what you want, it will have to use a loop internally, so you might as well use a loop yourself.
Edit:
If it is constant you can try something like this:
%Generating matrix struct results(a,b).randMin(c,d)
dim1=24;
dim2=5;
dim3=128;
dim4=11;
% value=0;
% for i=1:dim1
% for j=1:dim2
% for k=1:dim3
% for l=1:dim4
% results(i,j).randMin(k,l)=value;
% value=value+1;
% end
% end
% end
% end
%Getting the values
range1=1:24;
range2=1:5;
range3=1:4;
range4=2:dim4;
myMat=[results(range1, range2).randMin];
myContainer=reshape(myMat, dim3, dim4, length(range1), length(range2));
desiredValues=myContainer(range3, range4,:,:);
In the end, desiredValues will have the values you want, but the indices switched sides, instead of results(a,b).randMin(c,d) it is now desiredValues(c,d,a,b).
As I didn't know exactly how your struct looks like, I defined dim1 to dim4 as maximum values for the indices a to d. You can use range1 to range4 to select your desired values.

generate a name vector MATLAB

How would I generate a vector like
x1,x2,x3,x4,...,xn
the problem is concatenate ','and a 'x' char
n=100
A = (1:n);
This is a slight improvement on #Jonas's answer. SPRINTF will do the repeating for you avoiding the need for a mask:
>> n = 5;
>> out = sprintf('x%u,', 1:n);
>> out(end) = []
out =
x1,x2,x3,x4,x5
To generate the string 'x1,x2' etc, you can create a mask for SPRINTF using REPMAT like so:
n = 5;
mask = repmat('x%i,',1,n);
out = sprintf(mask,1:n);
out = out(1:end-1)
out =
x1,x2,x3,x4,x5
Note that in case you actually want to create a vector containing the strings 'x1','x2' etc, you'd use ARRAYFUN to generate a cell array:
out = arrayfun(#(x)sprintf('x%i',x),1:n,'uniformOutput',false)
out =
'x1' 'x2' 'x3' 'x4' 'x5'
The better answer is, don't do it. While you CAN do so, this will likely cause more heartache for you in the future than you want. Having hundreds of such variables floating around is silly, when you can use an array to index the same data. Thus perhaps x{1}, x{2}, ....