在Octave中实现Matlab的`num2str`行为

Lui*_*ndo 7 string matlab printf octave

以下代码

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

在Matlab中产生不同的结果(R20105b)

y =
 1.1 2.22 -3.3
4.44 5.55  6.6
Run Code Online (Sandbox Code Playgroud)

在Octave(4.0.0)

y =
1.1 2.22 -3.3
4.44 5.55 6.6
Run Code Online (Sandbox Code Playgroud)

不同之处在于对齐:在Matlab中,列是右对齐的,而在Octave中,它们没有对齐.

我想在Octave中完全实现Matlab的行为.你知道任何解决方案吗?当然我可以编写自己的函数,但也许已经存在一个解决方案.

编辑

另一个区别是如何处理多维数组.例如,

x = cat(3, magic(3), -magic(3));
fmt = '%.16g ';
y = num2str(x, fmt)
Run Code Online (Sandbox Code Playgroud)

在Matlab中生成

y =
8  1  6 -8 -1 -6
3  5  7 -3 -5 -7
4  9  2 -4 -9 -2
Run Code Online (Sandbox Code Playgroud)

在Octave

y =

8 1 6
3 5 7
4 9 2
-8 -1 -6
-3 -5 -7
-4 -9 -2
Run Code Online (Sandbox Code Playgroud)

也就是说,Matlab沿着第二维度附加3D切片,沿着第一维度附加八度切片.

Lui*_*ndo 2

这更像是一种解决方法,而不是解决方案;我对此并不完全满意。但事情就这样了。如果有人有更好或更通用的解决方案,请告诉。

以下仅适用于单个格式化运算符,如示例中所示(它不适用于类似 的东西fmt = '%.2f %.1f'),并且仅适用于实数(非复数)数字。它适用于具有多个2维度的数组,模仿 Matlab 的行为:它将第一个维度之外的所有维度折叠为单个(第二个)维度。

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
Run Code Online (Sandbox Code Playgroud)

这在 Matlab 和 Octave 中产生的结果与在 Matlab 中产生的结果相同y = num2str(x, fmt)

应该注意的是,当第一个输入是 char 数组时,num2str忽略第二个输入(格式说明符)并生成相同的 char 数组作为输出,无论是在 Matlab 中还是在 Octave 中。从而num2str('abc', '%f ')产生'abc'. 然而,sprintf工作方式不同:它强制使用格式说明符,如果需要,将输入的字符解释为 ASCII 代码。这就是if上面代码中需要分支的原因。