任何人都可以帮我构建和更正我的代码,目的只是保存任意方阵和其索引的非零元素吗?基本上我需要编写一个与MATLAB中的'sparse'功能相同的脚本。
`%Consider a 3x3 matrix
A=[ 0 0 9 ;-1 8 0;0 -5 0 ];
n=3; %size of matrix
%initialise following arrays:
RI= zeros(n,1); %row index
CI = zeros(n,1); %column index
V = zeros(n,1); %value in the matrix
for k = 1:n %row 1 to n
for j = 1:n %column 1 to n
if A(k,j)~=0
RI(k)=k;
CI(j)=j;
V(k,j)=A(k,j);
end
end
end`
答案 0 :(得分:0)
您可以使用find
function查找所有非零元素。
所以,
[RI, CI, V] = find(A);
% 2 1 -1
% 2 2 8
% 3 2 -5
% 1 3 9
编辑:
我从您的评论中意识到您的目标是在Matlab中学习编码,您可能想知道为什么您的代码没有按预期工作。因此,让我尝试解释该问题以及与您类似的示例代码。
% Given:
A = [0 0 9; -1 8 0; 0 -5 0];
首先,我建议不要手动指定尺寸为n = 3
,而是建议使用内置的size
功能。
sz = size(A);
% note that this contains 2 elements:
% [number of rows, number of columns]
接下来,要初始化数组RI
,CI
和V
,我们想知道它们的大小。由于我们不知道要开始的非零元素的数量,我们
有两个选项:(1)选择一个保证等于或大于非零元素数的大数,例如prod(sz)
。 (为什么这是真的?)。 (2)根本不要初始化它,让Matlab根据需要动态分配内存。我按照下面的代码中的第二个选项进行操作。
% we'll keep a count of non-zero elements as we find them
numNZ = 0; % this will increment every time a non-zero element is found
for iCol = 1:sz(2) %column 1 to end
for iRow = 1:sz(1) %row 1 to end
if A(iRow,iCol)~=0
numNZ = numNZ + 1;
RI(numNZ) = iRow;
CI(numNZ) = iCol;
V(numNZ) = A(iRow,iCol);
end
end
end
disp([RI, CI, V])
% 2 1 -1
% 2 2 8
% 3 2 -5
% 1 3 9
有道理吗?
答案 1 :(得分:0)
所以我认为我们已经确定了这一点,就是学习一种不熟悉的编程语言。最简单的解决方案是使用sparse
本身,但这使您无法深入了解编程。 find
也不能,可以类似地使用。
现在,我们可以使用您开始使用的相同路线:每行和每列的程序for
和if
。可能几乎是任何编程语言,但有一些标点符号的怪癖。但是你所发现的,即使你确实纠正了错误(比如n
应该是非零条目的数量,而不是行数),这是一种非常缓慢的方式在Matlab中做数值工作。
这是另一种(效率仍然低效,但不那么有效)的方式,希望能够提供一些对矢量化的信息。做事方式,这是让Matlab变得如此强大的事情之一:
function [RI, CI, V] = mysparse(A) % first: use functions!
[nRows, nCols] = size(A);
[allRowIndices, allColIndices] = ndgrid(1:nRows, 1:nCols) % let's leave the semicolon off so you can see for yourself what it does.
% It's very similar to `meshgrid` which you'll see more often (it's heavily used in Matlab graphics)
% but `ndgrid` is "simpler" in that it's more in tune with the fundamental conventions of Matlab (rows, then columns)
isNonZero = A ~= 0; % this gives you a "logical array" which is a very powerful thing: it can be used as a subscript to select elements from another array, in one shot...
RI = allRowIndices(isNonZero); % like this
CI = allColIndices(isNonZero); % or this
V = A(isNonZero); % or even this
RI = RI(:); % have to do this explicitly, because the lines above will reshape the values into a single long string under some circumstances but not others
CI = CI(:);
V = V(:);
答案 2 :(得分:0)
我将使用N x 3
矩阵,其中N
是矩阵中非零元素的数量。
% Define a matrix A as follows:
A = randi([0 1],[4 4])
for i=1:16
if A(i) ~= 0
A(i) = rand;
end
end
[row,col] = find(A);
elms = A(A~=0); % MATLAB always works in column-major order and is consistent,
% so no need to use sub2ind to access elements given by find
newSparse_A = [row col elms];
输出:
newSparse_A =
1.0000 1.0000 0.9027
2.0000 1.0000 0.9448
3.0000 1.0000 0.4909
1.0000 2.0000 0.4893
2.0000 2.0000 0.3377
4.0000 2.0000 0.9001
>> sparse(A)
ans =
(1,1) 0.9027
(2,1) 0.9448
(3,1) 0.4909
(1,2) 0.4893
(2,2) 0.3377
(4,2) 0.9001