Matlab格式编号固定为TOTAL宽度

时间:2015-07-28 20:41:08

标签: matlab number-formatting

我在Matlab中为特定的CFD代码编写了一个网格平滑器。网格数据文件的要求非常严格,因此数字格式必须非常具体。一个四边形单元的定义如下(其中第二行是x坐标,第三行是y坐标)。

    ELEMENT         14 [    1Q]    GROUP     0
   5.000000       10.00000       10.00000       5.000000    
   2.000000       2.000000       4.500000       4.500000

如您所见,每个数字恰好占用8个字符。一旦整个网格通过我的平滑器,我需要将数字写回文件。我最接近这个数字格式的是以下运算符:

%#7.7克

我认为我不能使用%f,因为这指定了小数点后的位数,在我的情况下变化(我的坐标从小于1变为超过100)。这个操作员给我的唯一问题是当我的数字小于1时,它只保留7个sig figs,数字最终为9个字符;例如:

0.9313373

有没有人知道正确的运营商,或者有解决方法?非常感谢。

2 个答案:

答案 0 :(得分:1)

这是我能想到的唯一解决方法:

A = [1.12341234 .12341234 20.12341234 5 10];

% Create a precision mask
maxwidth = 8; % Max width, characters
mask = maxwidth(ones(size(A))) - 1; % Initialize mask, account for decimal
mask(A < 1) = maxwidth - 2;

% Stack the vectors and weave them
temp = [mask(:)';A(:)'];
temp = temp(:);

test = sprintf('%#7.*g ', temp);

返回:

test =

1.123412 0.123412 20.12341 5.000000 10.00000 

这是一个令人讨厌的额外步骤,但我们可以利用sprintf的能力来获取星号,以便引用输入列表中的参数。由于我的sprintf调用和测试用例的设置方式,我将掩码和数据编织在一起,以便sprintf看到精度说明符和数据交替。如果您将原始temp(:)矩阵传递给temp,则sprintf调用是必要的,因为它会读取数据列主要内容,因此会执行相同的操作。我添加了它,因此行为更明确。

如何为您的实际打印例程制定sprintf调用将取决于您正在做什么,但这至少应该帮助您。

Edit1 :要展开,上述操作相当于:

a = sprintf('%#7.*g ', temp(1), temp(2));
b = sprintf('%#7.*g ', temp(3), temp(4));
c = sprintf('%#7.*g ', temp(5), temp(6));
d = sprintf('%#7.*g ', temp(7), temp(8));
e = sprintf('%#7.*g ', temp(9), temp(10));

test = [a b c d e];

Edit2 :已更新为帐户的整数值

Edit3 :请注意,目前这仅适用于正数

答案 1 :(得分:1)

单格式规范:

如果您的8个字符中只有4位精度(.之后的小数部分),并且网格读取程序可以处理填充0(即它是否可以读取值)像007.2365一样正确),那么最简单,最快捷的选择就是只使用格式说明符。

例如,让我们定义一个具有不同数量级的输入a

a=[  1 234    7             ;
    12   2    0.123456789   ;...
     5   2.36 0.0024      ] ;

您的最高数字是234,因此小数部分留下4位数。如果您接受矩阵中所有数字的精度,那么您只需设置一个简单的指令:

fmt='%08.4f %08.4f %08.4f\n'; %// hard coded format specifier
sprintf(fmt,a.')              %'// we transpose a to keep the same shape in the output since sprintf is column major.

ans =

001.0000 234.0000 007.0000
012.0000 002.0000 000.1235
005.0000 002.3600 000.0024

如果您事先不知道数据的最大数量级,您可以通过编程方式设置格式说明符:

nDigitTotal = 8 ;
nmax = ceil( log10(max(a(:))) ) ;        %// max order of magnitude of numbers in "a"
f   = sprintf('%%0%d.%df',nDigitTotal,nDigitTotal-nmax-1) ; %// format spec for 1 number
fmt = [f '\t' f '\t' f '\n'] ;                              %// format spec for a line of 3 numbers
s = sprintf(fmt,a.') 

将给出与上述相同的结果。 添加一项检查以确保矩阵中没有极端值会影响您的精确度。

个别格式规范:

最后,如果该精度和/或前导零不适合您,您可以采用更精细的解决方案。我非常喜欢设置掩码的excaza的想法,以指定每个数字的精度。我将生成我自己的版本,略有不同,它可以解释任何精度的数字并允许数组输出。然而,如果你最终使用这个解决方案,那么excaza应该归功于excaza,因为他是这种演变的灵感来源:

a = a.' ;                             %'// transpose from beginning/ thats done
nDigitTotal = 8;                      %// Total number of characters
mask = nDigitTotal(ones(size(a))) ;   %// Create mask

nOrder = floor( log10(a) ) ;          %// find order of magnitude of each element in the matrix
mask = mask - nOrder.*(nOrder>0) -1 ; %// adjust mask according to "nOrder" (only for nOrder>0)


temp = [mask(:)';a(:)'];              %// Stack the vectors and weave them

f = '%7.*f' ;                         %// basic format spec
fmt = [f '\t' f '\t' f '\n'] ;        %// build your line
sprintf(fmt,temp)                     %// go for it

会给你:

ans =

1.0000000   234.00000   7.0000000
12.000000   2.0000000   0.1234568
5.0000000   2.3600000   0.0024000

注意:使用格式说明符分隔符中的正常空格('\t')替换制表符(' '),具体取决于您的网格划分软件所期望的内容。