1

我目前在名为 template 的变量中有一个 5D 数组,它被写入名为 template1D 的 1D 数组中,其中包含 3456 个(8 * 12 * 3 * 4 * 3)个条目的哈希表。在 Matlab 中,多维数组的访问方式如下:

template{idx_r, idx_l, idx_rho, idx_alpha, idx_beta}

但是,由于我的索引分别从 0-7、0-11、0-2、0-3 和 0-2 开始,我不完全确定从这五个索引以便正确获取模板数组中的正确段。正确制作此类哈希函数的最简单方法是什么?

4

5 回答 5

7

不确定您在这里要做什么,但是您是否考虑过 ind2sub 和 sub2ind 函数?他们可能会有所帮助。您可能需要担心 0 与基于 1 的索引,因为 MATLAB 是基于 1 的。

——洛伦

于 2009-05-28T11:56:19.220 回答
3

如果它是一个排列为平面数组的二维数组,您将第一个索引乘以第一个维度的大小并添加第二个索引。同样,对于 5 个维度,您可以执行以下操作:

index = (((i1*l1 + i2)*l2 + i3)*l3 + i4)*l4 + i5;
于 2009-05-28T06:10:36.863 回答
2

您是否考虑过使用字符串进行哈希处理?你甚至可以把它变成一个十六进制数,

5 个字符

#Character 0 is in the range '0'...'7',
#Character 1 is in the range '0'...'B',
#Character 2 is in the range '0'...'2',
#Character 3 is in the range '0'...'3',
#Character 4 is in the range '0'...'2'

字符串作为十六进制数的部分优点在于,如果您需要转换,它也有一个简单的 int...err... unsigned long long 表示形式。

于 2009-05-28T06:04:31.197 回答
2

虽然您当然可以自己计算线性索引(如Tal所指出的),但使用内置函数SUB2IND(如Loren所指出的)会更清晰、更容易阅读。对于您的示例,您将按以下方式使用它:

index = sub2ind([8 12 3 4 3], idx_r, idx_l, idx_rho, idx_alpha, idx_beta);

如果您的所有索引都是从 0 开始的,那么您必须在将它们传递给 SUB2IND 之前给它们中的每一个加 1。

编辑:

如果您想了解如何在 MATLAB 中自己正确计算线性索引,以使它们与 SUB2IND 的结果一致,那么您将使用以下代码:

index = (((idx_beta*4 + idx_alpha)*3 + idx_rho)*12 + idx_l)*8 + idx_r + 1;

请注意,需要与此等式一起使用的索引必须从 0 开始,而传递给 SUB2IND 的索引必须从 1 开始。要将这个方程推广到任意维数N

index = (...(idx(N)*sz(N-1) + idx(N-1))*sz(N-2) + ...)*sz(1) + idx(1) + 1;

或更简洁地说:

index = 1 + sum(idx.*cumsum([1 sz(1:(N-1))]));

其中idx是每个维度的基于 0 的索引值的数组, sz是每个维度的大小数组。

于 2009-05-28T16:08:05.950 回答
0

我不知道我是否正确理解了这个问题,所以我将说明我的理解:

  • 您有一个给定大小的数组,它代表一个多维矩阵。
  • 您想将 5 维向量转换为数组的实际位置

我会首先创建一个类来封装它,然后我会提供使用 5 个参数(std::size_t、unsigned int 左右)定义的 operator()。这个 operator() 应该首先检查范围(可能会抛出异常并将所有参数转换为最终位置。

最简单的转换是:

size_t position( size_t idx_r, size_t idx_l, size_t idx_rho, size_t idx_alpha, size_t idx_beta )
{
   size_t pos = (((((((idx_r * dim_l) + idx_l) * dim_rho) + idx_rho) * dim_alpha) + idx_alpha) * dim_beta) + idx_beta;
   return pos;
}

其中dim_XXX表示第 XXX 维矩阵的大小。

如果您正在执行许多操作,您可能需要考虑在内部以不同的顺序表示数据,而不更改接口以获得更好的缓存命中率。

一般算法是将一个维度中的每个索引转换为后续维度元素,并在该维度添加偏移量。最简单的例子是二维系统。要访问 10 列数组上的第 3 行第 2 列(假设您按行存储,并且为了参数从 1 开始计数),您将首先计算第三行的开始,即每行 3 * 10 个元素。然后在第 2 行(第 2 列)内添加偏移量。

如果您将其扩展为 3 维数组,首先您必须通过将平面索引乘以平面的大小来找到您正在寻找的平面,然后使用前面的算法:

size_t position( size_t x, size_t y, size_t z )
{
   size_t start_of_plane_z = z * dim_y * dim_x; // z * size_of_plane
   size_t start_of_row_y = y * dim_x; // y * size_of_row
   size_t offset_inside_row = x;

   return start_of_plane_z + start_of_row_y + offset_inside_row;
}

现在,应用一些基本代数,您可以将方程变为:

size_t pos = (((z * dim_y) + y) * dim_x) + x;

这将减少乘法的数量,并且更容易为更多的维度定义。

于 2009-05-28T06:25:24.687 回答