我是一名物理学家,目前正在编写一个处理多维集成的C ++程序;特别是,我正在考虑的功能可以达到D = 9维。
从数学角度来看,我需要处理NxNxN ... xN(D次)矩阵,但从编程的角度来看,我被指示使用NxNxN ... xN元素的数组。据我所知,为了通用性和所有随后的涉及指针的计算,数组更好。
然而,现在我遇到了一个我无法解决的问题。
我需要执行一些计算,其中我的矩阵的单个索引是固定的,而所有其他索引都采用所有不同的值。
如果它是3x3x3矩阵,代码将类似于以下内容:
double test[3][3][3];
for(int i=0;i<3;i++) {
for(int j=0;j<3;j++) {
test[0][i][j]=i*j;
}
}
即。我可以修复索引并循环浏览其他索引。 同样的过程也可以扩展到第二和第三个索引。
如何使用double test[3*3*3]
完成相同的效果?请记住,三维矩阵只是一个例子;我正在处理的真实矩阵是9维的,所以我需要一种通用的方法来保持我的矩阵的单个索引固定并循环遍历所有其他矩阵。
TL; DR :我有一个代表NxNxN ... xN(9次)矩阵的数组。 我需要对数组执行一些计算,就好像我的矩阵的一个索引是固定的,而所有其他索引都循环遍历所有可能的值。
我知道在一维数组中映射二维矩阵的情况有一个简单的表达式;这里有类似的东西吗?
答案 0 :(得分:3)
通常,展平数组将按以下方式包含其元素:最后一个维度的元素将映射到重复的组,最内部的组将是背面的第二个维度,依此类推:
values[x][y][z] => { x0 = { y0_0 = { z0_0_0, z0_0_1, ..., z0_0_N }, y0_1 = { z0_1_0, z0_1_1, ... }, ... y0_N }, x1 = ... }
values[x*y*z] => { z0_0_0, z0_0_1, ..., z0_0_N, z0_1_0, z0_0_1, ... }
我希望这在我的大脑之外是有道理的。
因此,任何元素访问都需要计算,在它之前有多少块元素:
访问[2][1][3]
表示跳过2个x
块,每个块包含y
个z
个元素块,然后再跳过包含y
的另一个z
块{1}}元素并访问下一个块中的第3个元素:
values[2 * y * z + 1 * z + 3];
更常见的是N维d1, d2, d3 .. dn
和n维索引i1, i2, .. iN
:
[i1 * d2 * ... * dN + i2 * d3 * ... * dN + ... + iN]
回到你的例子:
double test[3*3*3];
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
// test[0*3*3 + i*3 + j] = i * j;
test[i*3 + j] = i * j;
}
}
答案 1 :(得分:3)
Raster scan是为两个维度排序元素的标准方法。
如果您有一个二维数组test[3][3]
,并且您通过test[i][j]
访问它,相应的一维数组将是
double raster[3 * 3];
您可以按如下方式访问它:
raster[i * 3 + j];
这可以推广到3个维度:
double raster[3 * 3 * 3];
...
raster[a * 9 + b * 3 + c];
或9维:
double raster[3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3];
...
raster[a * 6561 + b * 2187 + c * 729 + d * 243 + e * 81 + f * 27 + g * 9 + h * 3 + i];
让任何a ... i
索引变量保持不变,并在循环中更改其余变量,将访问9-D数组中的8-D切片。
您可能希望定义一些struct
来保存所有这些索引,例如:
struct Pos
{
int a, b, c, d, e, f, g, h, i;
};
然后您可以轻松地将位置转换为1-D索引:
int index(Pos p)
{
return p.a * 6561 + p.b * 2187 + p.c * 729 + p.d * 243 + p.e * 81 + p.f * 27 + p.g * 9 + p.h * 3 + p.i;
}
答案 2 :(得分:1)
如果矩阵的尺寸与所有尺寸相同,那么您可以像这样访问它们:
m[x + y*N + z*N*N + w*N*N*N ...]
如果尺寸不同,则会更复杂一些:
m[x + y*N1 + z*N1*N2 + w*N1*N2*N3 ...]