问题
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.
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?
回答1:
How to round off elements in a matrix in Octave:
There are many different ways to round a matrix and round a number in octave.
Option 1, use of sprintf format feature
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.
ans = 100.12
ans = 3.12
ans = 2.12
ans = 4.12
Option 2, round to significant digits using eval and 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
mymatrix2 =
100.0000 2.1200
3.1200 4.1200
Option 3, use the round function
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:
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)
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:
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.
回答2:
for those who want to get it working without digging deep into discussion why things are this way (namely octave round still does not support a second argument defining precision).
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
回答3:
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.
Put this function in a file called 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
来源:https://stackoverflow.com/questions/11386033/gnu-octave-round-a-number-to-units-precision