我很清楚比较花车所涉及的所有问题。这正是这个问题的原因
我正在寻找为3D矢量(3个浮点数 - x,y,z)的值创建快速哈希表。可以假设向量的长度始终为1.0(sqrt(x*x+y*y+z*z)
为1.0)
基本上这意味着我正在寻找一个散列函数,它接受几乎等于相同unsigned int值的值,以及一个相应的相等运算符,如果散列值相等则为true(不一定只有它们是等于)
修改 -
假阳性(即不同的矢量但映射到同一个桶)是给定的,因为这是一个哈希表
假阴性(即关闭但映射到不同桶的向量)是不合需要的,但似乎没有办法避免它们。在我的情况下,它们不会导致完全破损,只是一些数据重复,这是我不得不忍受的。
答案 0 :(得分:15)
我认为你所寻找的东西不是直接可能的。平等的一个重要特性是它具有传递性。 (即。如果a == b和b == c,则a == c)。但是,通过距离测量,您真的不需要这个属性。例如:
单个浮动(为简单起见)。假设我们想要散列每个浮点数,以便小于1e-3的浮点数是相同的值。现在,假设我们将所有1e-4分别添加到此哈希表1000浮点值。任何相邻的2个值都应该散列到同一个浮点数,因为它们比1e-3更接近。但是,由于传递性,这些值的邻居也应该具有相同的值,以及它们的邻居等等。结果,所有1000个值(包括相距1e-3的对)将散列为相同的整数。如果你要在图片上绘制这些点:
A B C D E F G H ... Y Z
假设所有间隙都是&lt;分开1e-3,但A和Z> 1e-3分开(不按比例!)。这是不能满足的,因为如果所有对的hash(A)== hash(B)和hash(B)== hash(C)等等(因为它们相距<1e-3)而不是hash( A)必须==哈希(Z)。
一种可能的选择是定义向量空间的区域,其中所有向量将散列到相同的值(即在对它们进行散列之前对它们进行舍入),但是仍然可以在它们各自的空间的边缘上获得2个向量一起但哈希到不同的值。您可以通过在所有相邻空间中搜索矢量来解决这个问题。 (即在上面的1-d情况下,你将所有向量四舍五入到最接近的1e-3的倍数,然后搜索邻居,因此5.3e-3将搜索5e-3,4e-3和6-e3。在高维情况下,您必须搜索所有维度的邻居。)
答案 1 :(得分:3)
我将浮点值转换为这样的整数:
unsigned int IntValue = (int)(floatValue * MULT) + MULT;
所以你得到一些第一个数字,然后使用
const MULT1 = (MULT << 1) + 1;
unsigned long long HashValue = (xIntValue * MULT1 * MULT1) + (yIntValue * MULT1) + zIntValue;
作为哈希值(使用(MULT * 2)+ 1,因为IntValues将介于0和MULT * 2之间)。
所需的内存取决于乘数MULT。例如,使用32,您将获得使用64 * 64 * 64 *(哈希项目大小)= 262144 *(哈希项目大小)字节的哈希表。
答案 2 :(得分:3)
某些语言(C,Java 5)允许您访问浮动的二进制值。这样,您可以提取尾数的前N位(忽略在比较期间导致问题的最后几位)并从中计算哈希值。
答案 3 :(得分:1)
你能说清楚你的问题吗?
假设您正在使用散列映射将一些附加数据映射到特定向量,您可以使用组件的二进制表示的XOR(如果可以使用您选择的语言)。然后根据哈希映射的需要使用尽可能多的LSB(以减少冲突)。这当然具有两个相等(通过浮点比较)向量可能不具有相同散列的属性(例如,IEEE浮点0等于-0,但它们具有不同的符号位)。
但是,如果您计划使用不同计算结果的向量进行哈希查找,那么您可能会因为舍入错误而无法使用匹配的哈希码,并且您可能应该使用其他东西
答案 4 :(得分:1)
我认为你正在有效地尝试解决最近的K问题。 我相信你要找的是locality sensitive hashing。 您也可以使用四叉树结构来获得相同的结果。
答案 5 :(得分:0)
不知道这可能有多快,但由于你有单位矢量,它们都位于球体的表面上。转换为http://en.wikipedia.org/wiki/Spherical_coordinate_system。然后用phi和theta来选择一个桶。不会有误报。你可以在邻近的细胞中查看假阴性。
答案 6 :(得分:0)
你需要它作为快速哈希表还是树结构呢?
在我看来,在某些搜索树中查找匹配的浮点数会更容易 分类。假设您选择正确的节点大小,B-Tree可以最大限度地减少缓存未命中数。这应该在实践中快速实现。