在doubles数组上使用unordered_map

Using unordered_map on array of doubles

本文关键字:unordered map doubles 数组      更新时间:2023-10-16

我的主数据对象是一个长度为双倍的数组,它取决于我的类的特定实例化。我想构建一个非常简单的哈希表来存储/检索这些对象,我们可以假设这些数字是以没有数字错误的方式生成的。

int main() {
  std::tr1::unordered_map<double*, double*> cache;
  double x1[] = { 1.0, 3.14 };
  double x2[] = { 1.0, 3.14 };
  cache[x1] = x1;
  std::cout << "x1: " << cache.count(x1) << std::endl;
  std::cout << "x2: " << cache.count(x2) << std::endl;
  return 0;
}

上面显然只比较了指针,给出了输出:

> ./tmp
x1: 1
x2: 0

当我真的想看:

> ./tmp
x1: 1
x2: 1

当数组的大小在编译时固定时,如何创建自定义哈希和等式函数是非常清楚的,但我不知道如何创建依赖于特定实例化的自定义函数。。。我在下面创建了一个类,但我不确定它是否有用,也不确定如何使用它。

class Hash_double_vec {
public:
  int dim;
  Hash_double_vec(int d) { dim = d; }
  size_t operator()(const double *x) const{
    std::tr1::hash<double> hash_fn;
    size_t r = hash_fn(x[0]);
    for(int i=1;i<dim;i++) r ^= hash_fn(x[i]);
    return r;
  }
  bool operator()(const double *x, const double *y) const{
    for(int i=1;i<dim;i++) if (fabs(x[i]-y[i]) > 1e-10) return false;
    return true;
  }
};

一种方法是创建一个结构来保存指向双打序列的指针:

struct DoubleRegion
{
    double* p;
    size_t size;
};
bool operator==(DoubleRegion a, DoubleRegion b)
{
    return a.size == b.size && memcmp(a.p, b.p, a.size) == 0;
}
size_t hash(DoubleRegion dr) 
{
    size_t h = 0;
    for (double* p = dr.p; p != dr.p + dr.size; ++p)
        h ^= hash(*p);
    return h;
}

然后使用它:

unordered_map<DoubleRegion, DoubleRegion> cache;

当然,确保备份内存的生存期是DoubleRegion生存期的超集是您的问题。

旧答案

如果直到运行时才知道键和值的大小,请使用std::vector:

unordered_map<vector<double>, vector<double>> cache;

如果您在编译时知道可以使用std::array:的大小

unordered_map<array<double, N>, array<double, N>> cache;

在这两种情况下,默认哈希函数都将根据您的需要按值工作,并且您不需要定义自定义哈希函数。