Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Achieve Matlab's `num2str` behaviour in Octave

The following code

x = [1.1, 2.22, -3.3; 4.44, 5.55, 6.6];
fmt = '%.16g ';
y = num2str(x, fmt)

produces different results in Matlab (R20105b)

y =
 1.1 2.22 -3.3
4.44 5.55  6.6

and in Octave (4.0.0)

y =
1.1 2.22 -3.3
4.44 5.55 6.6

The difference is the alignment: in Matlab the columns are right-aligned, whereas in Octave they are not aligned.

I'd like to achieve exactly Matlab's behaviour in Octave. Do you know any solution for this? Of course I could write my own function, but maybe there already exists a solution.

EDIT

Another difference is how multidimensional arrays are treated. For example,

x = cat(3, magic(3), -magic(3));
fmt = '%.16g ';
y = num2str(x, fmt)

produces in Matlab

y =
8  1  6 -8 -1 -6
3  5  7 -3 -5 -7
4  9  2 -4 -9 -2

and in Octave

y =

8 1 6
3 5 7
4 9 2
-8 -1 -6
-3 -5 -7
-4 -9 -2

That is, Matlab attaches the 3D slices along the second dimension, and Octave along the first.

like image 291
Luis Mendo Avatar asked Dec 27 '15 19:12

Luis Mendo


1 Answers

This is more of a workaround than a solution; and I'm not totally satisfied with it. But here it goes. If anyone has a better or more general solution please tell.

The following only works for a single formatting operator, as in the example (it doesn't work for something like fmt = '%.2f %.1f'), and only for real (not complex) numbers. It works for arrays with more than 2 dimensions, mimicking Matlab's behaviour: it collapses all dimensions beyond the first into a single (second) dimension.

if ischar(x)
    y = x;
else
    y = sprintf([fmt '\n'], reshape(x,size(x,1),[]).'); %'// each row of y is a string.
                                                        % // '\n' is used as separator
    y = regexp(y, '\n', 'split'); %// separate
    y = y(1:end-1).'; %'// remove last '\n'
    y = cellfun(@fliplr, y, 'uniformoutput', false); %// invert each string
    y = char(y); %// concatenate the strings vertically. This aligns to the left
    y = fliplr(y); %// invert back to get right alignment
    y = reshape(y.',[],size(x,1)).'; %// reshape into the shape of x
    y = strtrim(y); %// remove leading and trailing space, like num2str does
end

This produces, both in Matlab in Octave, the same result as produced by y = num2str(x, fmt) in Matlab.

It should be noted that when the first input is a char array num2str ignores the second input (format specifier) and produces as output the same char array, both in Matlab and in Octave. Thus num2str('abc', '%f ') produces 'abc'. However, sprintf works differently: it forces the use of the format specifier, interpreting the chars of the input as ASCII codes if needed. That's why the if branch is needed in the above code.

like image 75
Luis Mendo Avatar answered Oct 09 '22 23:10

Luis Mendo