Linux GNU Octave,将数字四舍五入到单位精度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11386033/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 13:44:23  来源:igfitidea点击:

GNU Octave, round a number to units precision

linuxmatrixroundingprecisionoctave

提问by Eric Leschinski

In GNU Octave version 3.4.3 I want to round a matrix to 2 units precision on the contents of a matrix like this.

在 GNU Octave 3.4.3 版中,我想将矩阵四舍五入到像这样的矩阵内容的 2 个单位精度。

mymatrix=[1.1234567, 2.12345; 3.1234567891, 4.1234];
disp(mymatrix);

This prints:

这打印:

1.1235   2.1235
3.1235   4.1234

As you can see, the disp forces the precision to '5', I want the units precision to be 2. How do I do this?

如您所见,显示强制精度为“5”,我希望单位精度为 2。我该怎么做?

采纳答案by Eric Leschinski

How to round off elements in a matrix in Octave:

如何在 Octave 中舍入矩阵中的元素:

There are many different ways to round a matrix and round a number in octave.

有许多不同的方法来舍入矩阵和以八度为单位舍入数字。

Option 1, use of sprintf format feature

选项1,使用sprintf格式功能

mymatrix=[100.1234567, 2.12345; 3.1234567891, 4.1234];
rows = rows(mymatrix);
cols = columns(mymatrix);
for i = 1:rows
  for j = 1:cols
    sprintf("%5.2f", mymatrix(j,i))
  endfor
endfor

Output, note the "%5.2f" token. The 'f' means expect a float, the 5 means occupy 5 spaces. The 2 means 2 units precision after the decimal point.

输出,注意“%5.2f”标记。'f' 表示期望一个浮点数,5 表示占用 5 个空格。2 表示小数点后 2 个单位的精度。

ans = 100.12
ans =  3.12
ans =  2.12
ans =  4.12

Option 2, round to significant digits using eval and mat2str

选项 2,使用 eval 和 mat2str 舍入到有效数字

mymatrix2=[100.1234567, 2.12345; 3.1234567891, 4.1234];
j = mat2str(mymatrix2, 3);
mymatrix2=eval(j)

Output, matrix rounded to 3 significant digits, notice 100.123 rounded to 100 while the 2.12345 was rounded to 2.12

输出,矩阵四舍五入为 3位有效数字,注意 100.123 四舍五入为 100 而 2.12345 四舍五入为 2.12

mymatrix2 =
   100.0000     2.1200
     3.1200     4.1200

Option 3, use the round function

选项3,使用round函数

The round function does not have a precision parameter in Octave. However you can hack around it by multiplying each item in the matrix by 100, rounding it to the nearest int, then dividing each item by 100:

圆函数在 Octave 中没有精度参数。但是,您可以通过将矩阵中的每个项目乘以 100,将其四舍五入到最接近的整数,然后将每个项目除以 100 来绕过它:

mymatrix=[100.1234567, 2.12345; 3.1234567891, 4.1234];
round(mymatrix .* 100) ./ 100

Output, round occurs correctly:

输出,回合正确发生:

ans =
   100.1200     2.1200
     3.1200     4.1200

Option 4, specify a output_precision(num)

选项 4,指定一个 output_precision(num)

You noticed that option 3 above kept the trailing zeros, which may be undesirable, so you can tell them to go away by setting output_precision:

您注意到上面的选项 3 保留了尾随零,这可能是不可取的,因此您可以通过设置 output_precision 告诉它们消失:

mymatrix=[100.1234567, 2.12345; 3.1234567891, 4.1234];
disp(mymatrix);
output_precision(3)
disp(mymatrix)

Output:

输出:

100.1235     2.1235
  3.1235     4.1234

100.123     2.123
  3.123     4.123

Octave can have some really odd behavior when trying to do rounding, remember, that octave tries hard to uniformly apply rounding to all items in a matrix. So if you have multiple columns with wildly different values, octave may look at one partcularly tiny value and think: "Hey, I should convert that to exponential: 0.0001 to 1.0e-04, and thus, the same thing is applied to the entire matrix.

Octave 在尝试进行舍入时可能会出现一些非常奇怪的行为,请记住,octave 会努力将舍入均匀地应用于矩阵中的所有项目。因此,如果您有多个具有截然不同值的列,octave 可能会查看一个特别小的值并认为:“嘿,我应该将其转换为指数:0.0001 到 1.0e-04,因此,同样的事情适用于整个矩阵。

回答by Eric Leschinski

I've found the following GNU Octave function tremendously useful. This lets you specify a custom rounding for each individual column of a MxN matrix.

我发现以下 GNU Octave 函数非常有用。这使您可以为 MxN 矩阵的每一列指定自定义舍入。

Put this function in a file called display_rounded_matrix.m

将此函数放在名为 display_rounded_matrix.m 的文件中

function display_rounded_matrix(matrix, precision, outputFile)
  %precision can be a single number, applied to all, or a 
  %matrix of values to be applied to the columns. 

  space_between_columns = "";
  format_part = "%10.";

  precision_format = cell(columns(precision), 1);
  for i = 1:columns(precision),
    precision_format{i,1} = strcat(format_part, num2str(precision(1,i)), "f");
  end

  if (nargin == 3 && outputFile != 0)
    if (rows(precision) == 1 && columns(precision) == 1)
      rows = rows(matrix);
      cols = columns(matrix);
      format = strcat(format_part, num2str(precision), "f");
      for i = 1:rows
        for j = 1:cols
          fprintf(outputFile, sprintf(format, matrix(i,j)));
          if (j ~= cols)
            fprintf(outputFile, space_between_columns);
          end
        end
        if i ~= rows
          fprintf(outputFile, "\n");
        end
      end
      fprintf(outputFile, "\n");
    elseif (rows(precision) == 1 && columns(precision) == columns(matrix))
      %here we have to custom make the rounding
      rows = rows(matrix);
      cols = columns(matrix);
      for i = 1:rows
        for j = 1:cols
          fprintf(outputFile, sprintf(precision_format{j,1}, matrix(i,j)));
          if (j ~= cols)
            fprintf(outputFile, space_between_columns);
          end
        end
        if i ~= rows
          fprintf(outputFile, "\n");
        end
      end
      fprintf(outputFile, "\n");
    else
      disp("STOP!, you invoked display_rounded_matrix with bad parameters");
    end

  elseif (nargin == 3 && outputFile == 0)
%print to screen instead

if (rows(precision) == 1 && columns(precision) == 1)
      rows = rows(matrix);
      cols = columns(matrix);
      format = strcat(format_part, num2str(precision), "f");
      for i = 1:rows
        for j = 1:cols
          printf(sprintf(format, matrix(i,j)));
          if (j ~= cols)
            printf(space_between_columns);
          end
        end
        if i ~= rows
          printf("\n");
        end
      end
      printf("\n");
    elseif (rows(precision) == 1 && columns(precision) == columns(matrix))
      %here we have to custom make the rounding
      rows = rows(matrix);
      cols = columns(matrix);
      for i = 1:rows
        for j = 1:cols
          %format = strcat(format_part, num2str(precision(1,j)), "f");
          format = [format_part num2str(precision(1,j)) "f"];
          printf(sprintf(format, matrix(i,j)));
          if (j ~= cols)
            printf(space_between_columns);
          end
        end
        if i ~= rows
          printf("\n");
        end
      end
      printf("\n");
    else
      disp("STOP!, you invoked display_rounded_matrix with bad parameters");
    end

  elseif (nargin == 2)
    display_rounded_matrix(matrix, precision, 0);
  else
    disp("STOP!, you invoked display_rounded_matrix with wrong number of arguments");
  end
end

Then you can invoke it like this:

然后你可以像这样调用它:

A = [ 53.0 410400  0.0094; 52.56 778300 -0.0069; 53.56 451500 -0.0340 ];
specified_rounding = [2 0 5];
display_rounded_matrix(A, specified_rounding, outputFile=0);

This will display the following on the screen (notice the different roundings for each column!

这将在屏幕上显示以下内容(注意每列的不同四舍五入!

octave:5> display_rounded_matrix(A, specified_rounding, outputFile=0);
  53.00    410400   0.00940
  52.56    778300  -0.00690
  53.56    451500  -0.03400

the 3rd parameter is a file handle, you could redirect the output to a file too:

第三个参数是文件句柄,您也可以将输出重定向到文件:

outputFile = fopen("output.txt", "w");
A = [ 53.0 410400  0.0094; 52.56 778300 -0.0069; 53.56 451500 -0.0340 ];
specified_rounding = [2 0 5];
display_rounded_matrix(A, specified_rounding, outputFile);

Which will do the same thing as above, but send the output to output.txt

这将做与上面相同的事情,但将输出发送到 output.txt

回答by Ufos

for those who want to get it working without digging deep into discussion why things are this way (namely octave roundstill does not support a second argument defining precision).

对于那些想要让它工作而不深入讨论为什么事情是这样的人(即八度round仍然不支持定义精度的第二个参数)。

WORKAROUND:

解决方法

a = [0.056787654, 0.0554464; 0.056787654, 0.0554464];
a
round_digit = 2;
if exist('OCTAVE_VERSION', 'builtin') ~= 0;
     a = a.*(10^(round_digit));
     a = floor(a);
     a = a.*(10^(-round_digit));
else
     a = round(a, round_digit);
end
a