我的哈希函数有问题吗?

Is something wrong with my hash function

本文关键字:有问题 函数 哈希 我的      更新时间:2023-10-16

>我正在尝试实现空间哈希,并使用优化空间哈希中的哈希函数进行可变形对象的碰撞检测,hash(x, y, z) = (x p1 xor y p2 xor z p3) mod n其中 n 是哈希表中的存储桶数。

我的哈希函数代码是:

int SpatialHash::hash(int x, int y, int z)
{
    return (((x * P1) ^ (y * P2) ^ (z * P3)) % TABLE_SIZE);
}

定义:

#define P1 73856093
#define P2 19349663
#define P3 83492791
#define TABLE_SIZE 2000

刚刚尝试遍历元素列表,当我尝试将顶点 1、-1、0 放入表中时,它给了我一个 -196 的索引。我的哈希函数在某个地方搞砸了吗?

负数的模是负数。例如:

-7 % 3 = -1

什么想要这样的东西:

int positiveModulo(int number, int modulo)
{
    int result = number % mudulo;
    if (result < 0)
        result += modulo;
    return result;
}

或者避免分支:

int positiveModulo(int number, int modulo)
{
    int result = number % mudulo;
    result += modulo;
    result %= modulo;
    return result;
}

这将为您提供:

positiveModulo(-7, 3) = 2

这实际上是一个有趣的问题,因为模运算结果的符号是编程语言设计者和数学家喜欢争论的东西。

实际上,在ISO C++中,带有负操作数的模运算的符号是实现定义的。聪明的语言既有mod,也有rem来捕捉这两种情况。看看维基百科页面和他们的编程语言表。

有趣的是,它是如何被分割的,接近 50:50。

现在问题的解决方案:只需添加一个正模运算。最简单的解决方案是使用 abs(...) % N ,如(-a) mod N + a mod N = 0

#include <iostream>
#include <vector>
using namespace std;
#define P1 73856093
#define P2 19349663
#define P3 83492791
#define TABLE_SIZE 2000
int positive_mod(int i, int n)
{
    /* constexpr */ int shift = 64*sizeof i - 1;
    int m = i%n;
    return m+ (m>>shift & n);
}
int hasha(int x, int y, int z)
{
    return positive_mod(((x * P1) ^ (y * P2) ^ (z * P3)) ,TABLE_SIZE);
}


int main(int argc, char **argv)
{
    int ret = hasha(1,-1,0);
    cout << ret << endl;
}