应用hashCode()时如何获得积极的结果?

时间:2017-12-09 07:18:50

标签: scala range hashcode

我正在研究将唯一字符串集转换为唯一ID的Scala代码。我应用了HashCode(),但我得到了负数,我只需要使用正数。 我知道我必须使用math.abs去除负值,但我不确定这是否是正确的解决方案。 如果我之前读过这样的话可以解决我的问题

math.abs(hashCode()) * constant % size

如何确定正确的常数?并且大小是指字符串的总数吗?

与该主题相关的先前问题仅通过使用math.abs解决了问题,但如果字符串的总数很大,则可能发生溢出,并且还有可能获得负数。通过将结果乘以常数并取大小的mod可能会有所帮助。这就是为什么我需要了解如何确定常数和大小?

还有另一种方法可以获得唯一字符串的唯一数字吗?

2 个答案:

答案 0 :(得分:0)

我们可以用另一种方式说明您的问题:如何从具有相同范围的签名号码中获取无符号号码?

假设您使用的是Integer。它的值从-2147483648到2147483647.现在你需要将这个值转换为正值范围0到2147483647。

第1步:
添加常量可将范围向上移动到0.您可以通过向值添加2147483648来执行此操作。但现在最高可能值远大于MAX。

第2步:
因此,请使用MODULO将值移回所需范围。

例如,考虑值-2000和2000000000。

| STEP              | MIN VALUE  | EXAMPLE 1  | EXAMPLE 2  | MAX VALUE  |
|-------------------|------------|------------|------------|------------|
| original          |-2147483648 |   -2000    | 2000000000 | 2147483647 |
| add 2147483648    |     0      | 2147481648 | 4147483648 | 4294967295 |
| modulo 2147483648 |     0      | 2147481648 | 2000000001 | 2147483647 |

所以最终的公式是:

(NUMBER + 2147483648) % 2147481648
  

警告:
  散列码不是为了给出唯一值而设计的。有可能为两个不同的字符串获取相同的哈希值。此外,散列上的任何缩放操作(如除法,模数)都可以进一步降低唯一性。

答案 1 :(得分:0)

要从Int剥离标记,您只需使用.abs即可。它确实在Int.MinValue上中断,但你可以特别注意它:

def stripSign(n: Int) = math.abs(n) max 0

或只是删除符号位:

def stripSign2(n: Int) = n & Int.MaxValue

或者只是使用负数(无论如何它们都有问题?)。

对于您的另一个问题,您无法将一堆唯一字符串转换为整数,并保证不会出现重复(原因很简单,因为 more 字符串比distinct {{1因此,如果你想为它们中的每一个分配一个唯一的int,那么在你的字符串用完之前你就会用完整数),所以你必须能够处理碰撞,不过很少。

你只能通过延长哈希值来降低发生冲突的概率(使用32位哈希码,在大约75000个字符串的群体中,你有大约50%的概率至少发生一次冲突,31位(如果你不想要负数),它是55000,但是如果你的哈希函数足够好,那么使用64位哈希,“幻数”约为5 十亿,并产生分布均匀的数字)。