我面临着有几个整数的问题,我必须使用它们生成一个整数。例如。
Int 1: 14
Int 2: 4
Int 3: 8
Int 4: 4
Hash Sum: 43
我对这些值有一些限制,和属性可以有的最大值是30,所有这些值的加法总是30.并且属性总是正的。
关键是我想为类似的整数生成相同的哈希值,例如,如果我有整数,14,4,10,2,那么我想生成相同的哈希值,在43以上的情况下。但是当然如果整数非常不同(4,4,2,20)那么我应该有一个不同的哈希值。它也需要快速。
理想情况下,我希望哈希和的输出介于0和512之间,并且它应该均匀分布。由于我的限制,我可以有大约5K种不同的可能性,所以我想要的是每桶10个左右。
我确信有很多算法可以做到这一点,但我找不到谷歌搜索这个东西的方法。任何人都可以发布算法来做到这一点吗?。
更多信息
这一切的全部内容是那些整数是函数的属性。我想将函数的值存储在表中,但是我没有足够的内存来存储所有不同的选项。这就是我想在类似属性之间进行概括的原因。
10,5,15与5,10,15完全不同的原因是因为如果你想象这在3D中那么两点都是完全不同的点
更多信息2
有些答案尝试使用散列来解决问题。但我不认为这太复杂了。感谢其中一条评论,我意识到这是一个聚类算法问题。如果我们只有3个属性并且我们想象3d中的问题,我只需要将块空间分开。
事实上,这可以通过此类规则来解决
if (att[0] < 5 && att[1] < 5 && att[2] < 5 && att[3] < 5)
Block = 21
if ( (5 < att[0] < 10) && (5 < att[1] < 10) && (5 < att[2] < 10) && (5 < att[3] < 10))
Block = 45
问题是我需要一种快速而通用的方法来生成那些我无法写出所有可能性的ifs。
答案 0 :(得分:5)
简单的解决方案:
将整数转换为以逗号分隔的字符串,并使用常用的散列算法(md5,sha等)对生成的字符串进行散列。
如果你真的想要自己动手,我会做类似的事情:
要生成散列,请计算:sum(a [i] * x [i])mod P
答案 1 :(得分:4)
给定输入a,b,c和d,每个值的范围从0到30(5位),以下将产生0到255(8位)范围内的数字。
bucket = ((a & 0x18) << 3) | ((b & 0x18) << 1) | ((c & 0x18) >> 1) | ((d & 0x18) >> 3)
一般方法是否合适取决于问题的解释方式。删除3个最低有效位,在同一组中分组0-7,在下一组中分组8-15,依此类推。
0-7,0-7,0-7,0-7 -> bucket 0
0-7,0-7,0-7,8-15 -> bucket 1
0-7,0-7,0-7,16-23 -> bucket 2
...
24-30,24-30,24-30,24-30 -> bucket 255
通过以下方式进行简单测试:
for (int a = 0; a <= 30; a++)
for (int b = 0; b <= 30; b++)
for (int c = 0; c <= 30; c++)
for (int d = 0; d <= 30; d++) {
int bucket = ((a & 0x18) << 3) |
((b & 0x18) << 1) |
((c & 0x18) >> 1) |
((d & 0x18) >> 3);
printf("%d, %d, %d, %d -> %d\n",
a, b, c, d, bucket);
}
答案 2 :(得分:2)
您想要一个取决于输入顺序的哈希函数,以及类似的数字集合将生成相同的哈希值?也就是说,您希望50 5 5 10和5 5 10 50生成不同的值,但是您希望52 7 4 12生成与50 5 5 10相同的哈希值?做这样的事情的简单方法是:
long hash = 13;
for (int i = 0; i < array.length; i++) {
hash = hash * 37 + array[i] / 5;
}
这不完美,但应该让您了解实现所需内容的一种方法。它会将值50 - 54视为相同的值,但它会将49和50视为不同的值。
如果您希望散列与输入的顺序无关(因此5 10 20和20 10 5的散列相同),那么执行此操作的一种方法是将整数数组按升序排序应用哈希。另一种方法是替换
hash = hash * 37 + array[i] / 5;
与
hash += array[i] / 5;
编辑:考虑到您对此回答的评论,听起来我的上述尝试可能足以满足您的需求。它不是理想的,也不是完美的。如果你需要高性能,你需要做一些研究和实验。
总而言之,顺序非常重要,因此5 10 20与20 10 5不同。另外,理想情况下,您可以将每个“向量”分别存储在哈希表中,但要处理空间限制,要将某些值存储在一个表项。
理想的哈希函数会根据您的表大小返回一个均匀分布在可能值上的数字。这样做取决于表的预期大小以及输入向量值的数量和预期的最大值。如果您可以将负值作为“坐标”值,那么这可能会影响您计算哈希的方式。如果给定您的输入值范围和所选的哈希函数,您的最大哈希值小于哈希表大小,那么您需要更改哈希函数以生成更大的哈希值。
答案 3 :(得分:1)
您可能希望尝试使用vectors将每个数字集描述为哈希值。
编辑: 既然你没有描述为什么你不想自己运行这个函数,我猜它已经很久了。由于您尚未描述参数集的广度。
如果每个值都是预期的,那么数据库中的完整查找表可能会更快。
如果您期望使用相同的参数重复调用并且整体变化很小,那么您可以查看memoizing,因此只有参数集的第一次运行是昂贵的,并且每个额外的请求都很快,而且更少内存使用情况。
答案 4 :(得分:0)
您需要定义“类似”的含义。哈希通常旨在通过独特的输入创建独特的结果。
一种方法是规范化输入,然后从结果中生成哈希值。
答案 5 :(得分:0)
生成相同的哈希值称为冲突,对于哈希来说是一件坏事。它使它没那么有用。
如果您希望类似的值给出相同的输出,您可以将输入除以您希望它们计算的距离。如果订单有所不同,请为每个数字使用不同的除数。以下函数执行您所描述的内容:
int SqueezedSum( int a, int b, int c, int d )
{
return (a/11) + (b/7) + (c/5) + (d/3);
}
这不是哈希,而是你所描述的。
答案 6 :(得分:0)
您想查看geometric hashing。在“标准”哈希中你想要
使用几何哈希,你可以使用几乎相反的东西来编号3;即close初始值给出紧密的哈希值。
答案 7 :(得分:0)
查看我的问题的另一种方法是使用多维缩放(MS)。在MS中,我们从项目矩阵开始,我们想要的是将每个项目的位置分配给N维空间。以这种方式减少尺寸数量。