在c#中有效地复制对称矩阵

我想在一个数组中存储一个对称矩阵

对于矩阵我正在这样做

double[,] mat = new double[size,size]; for (int i = 0; i < size; i++) { for (int j = 0; j <= i; j++) mat[i, j] = mat[j, i] = (n * other_matrix[i,j]); } 

如果我想存储在一个数组中

 double[] mat = new double[size*size]; 

代替

  double[,] mat 

什么是最有效的方式?

使用mat[i*n+j]

是。

按行存储元素,其中第i行和第j列存储在索引k=i*NC+j其中NC为列数。 这适用于非对称通用矩阵。

要存储大小为N的对称矩阵,您只需要在数组中使用N*(N+1)/2元素。 您可以假设i<=j ,使得数组索引如下所示:

 k(i,j) = i*Ni*(i+1)/2+j i<=j //above the diagonal k(i,j) = j*Nj*(j+1)/2+i i>j //below the diagonal 

 i = 0 .. N-1 j = 0 .. N-1 

例如,当N = 5时,数组索引就是这样的

 | 0 1 2 3 4 | | | | 1 5 6 7 8 | | | | 2 6 9 10 11 | | | | 3 7 10 12 13 | | | | 4 8 11 13 14 | 

所需的总元素是5*(5+1)/2 = 15 ,因此索引从0..14校验

i个对角线具有索引k(i,i) = i*(N+1)-i*(i+1)/2 。 因此第3行( i=2 )具有对角线索引k(2,2) = 2*(5+1)-2*(2+1)/2 = 9校验

i行的最后一个元素具有index = k(i,N) = N*(i+1)-i*(i+1)/2-1 。 所以第3行的最后一个元素是k(2,4) = 5*(2+1)-2*(2+1)/2-1 = 11校验

您可能需要的最后一部分是如何从数组索引k到行i和列j 。 再假设i<=j (在对角线上方)答案是

 i(k) = (int)Math.Floor(N+0.5-Math.Sqrt(N*(N+1)-2*k+0.25)) j(k) = k + i*(i+1)/2-N*i 

为了检查上面的内容,我运行N=5k=0..14 ,得到以下结果:

索引表

哪个是对的! 校验

要制作副本,只需对Array.Copy()的元素使用Array.Copy() 。 另外,要进行添加和缩放等操作,只需要处理数组中的简化元素,而不是完整的N*N矩阵。 矩阵乘法有点棘手,但可行。 如果你愿意,也许你可以提出另一个问题。

关于选定的答案,除非我是一个完全白痴,否则代码不正确:

试试这个:

 i = 2, j = 1 therefore we use: k(i,j) = j*Nj*(j-1)/2+i to find the index k, solving: k(i,j) = 1*5 - 1*(1-1)/2 + 2 k(i,j) = 5 - 0 + 2 = 7 

从所选答案中的矩阵我们看到(2,1)不是7,它似乎是6.事实上(因为这似乎是0基),7发生在(3,1)或(1, 3)。 i> j的第二个公式似乎不准确,除非我遗漏了一些东西。

更新:

如果你改变i> j公式,这似乎有效:

 k(i,j) = j*(N-1)-j*(j-1)/2+i 

如果n是方阵的大小,则对称矩阵需要n *(n + 1)/ 2个总值。 这是1 + 2 + 3 + …(n – 2)+(n – 1)+ n的总和。

但需要注意的是,总是试图计算给定行和列的正确索引会非常痛苦,如果矩阵将会是更加直观的二维数组,那么我只会放弃它。大,记忆将成为一个问题。