【问题标题】:5D array hash table5D 数组哈希表
【发布时间】:2010-10-29 11:51:48
【问题描述】:

我目前在名为 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 开始,因此我不完全确定检索整体的最简单方法是什么这五个索引中的索引号,以便正确获取模板数组中的正确段。正确制作此类哈希函数的最简单方法是什么?

【问题讨论】:

  • 五个花了时间回答零,认为这是一个足够好的问题来投票。我愿意 +1

标签: c++ matlab hashtable


【解决方案1】:

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

--洛伦

【讨论】:

  • 是的,欢迎!很高兴看到更多的 MathWorkers 出现在这里……尽管这意味着回答问题的竞争更加激烈。 =)
【解决方案2】:

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

index = (((i1*l1 + i2)*l2 + i3)*l3 + i4)*l4 + i5;

【讨论】:

  • 这实际上是 SUB2IND 在 MATLAB 中为您所做的。
  • 我认为您的等式中的尺寸可能不正确。对于二维数组,您可以将第一个索引乘以 second 维度的大小并添加第二个索引。扩展到更大维度的数组,它将是: index = (((i1*l2 + i2)*l3 + i3)*l4 + i4)*l5 + i5;
  • 感谢您的建议。我会让你知道我的差异如何显示在你的建议和我在 Matlab 中使用 sub2ind 获得的相同索引之间。
  • 已修复差异。谢谢新手。
【解决方案3】:

虽然您当然可以自己进行数学运算来计算线性索引(如 Tal 所指出的那样),但使用内置函数 SUB2IND(如 @987654323 所指出的那样)会更简洁、更易于阅读@)。对于您的示例,您可以通过以下方式使用它:

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 是每个维度的大小数组。

【讨论】:

  • 在任何 C++ 库中是否有类似的函数不使用执行类似操作的 mex 函数?如果它存在,我很难找到它。
  • 我还没有遇到过相当于 SUB2IND 的 C++。您是否需要在您正在编写的 mex 文件中进行索引?我知道有一个名为“mexCallMATLAB”(mathworks.com/support/tech-notes/1600/1605.html#example5) 的函数允许您从 mex 文件调用 MATLAB 函数,但这可能只适用于 C。
  • 目前,我将 C++ 代码作为 mex 文件运行,但最终我不会这样做,因此问题是除了接受的答案之外是否还有 C++ 等价物。
  • 在这种情况下,我会选择 Tal 的答案。根据他给出的公式编写自己的小函数可能是你做的最快和最简单的事情。
  • 我刚刚在 Matlab 中使用相同的索引检查了 sub2ind 函数(除了它们在 C++ 中偏移 1,因为数组索引从 0 开始),计算的索引看起来与 Tal 的答案不同。偏移量可能是我得到这种差异的原因吗?
【解决方案4】:

您是否考虑过使用字符串进行哈希处理?您甚至可以将其设为十六进制数,

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 表示形式,如果您需要转换的话。

【讨论】:

  • 即使使用字符串进行散列,我如何从模板数组中获取相应的段?
  • 将您的字符串转换为 5 个单独的整数,每个字符 1 个,将是微不足道的。我不使用 matlab - 我在这里遗漏了什么吗?
【解决方案5】:

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

  • 您有一个给定大小的数组,它表示一个多维矩阵。
  • 您想将 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;

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

【讨论】:

    猜你喜欢
    • 2011-07-23
    • 2011-08-22
    • 2017-03-14
    • 1970-01-01
    • 1970-01-01
    • 2017-04-13
    • 2012-11-11
    • 2013-01-05
    • 1970-01-01
    相关资源
    最近更新 更多