我正在研究将唯一字符串集转换为唯一ID的Scala代码。我应用了HashCode(),但我得到了负数,我只需要使用正数。 我知道我必须使用math.abs去除负值,但我不确定这是否是正确的解决方案。 如果我之前读过这样的话可以解决我的问题
math.abs(hashCode()) * constant % size
如何确定正确的常数?并且大小是指字符串的总数吗?
与该主题相关的先前问题仅通过使用math.abs解决了问题,但如果字符串的总数很大,则可能发生溢出,并且还有可能获得负数。通过将结果乘以常数并取大小的mod可能会有所帮助。这就是为什么我需要了解如何确定常数和大小?
还有另一种方法可以获得唯一字符串的唯一数字吗?
答案 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 十亿,并产生分布均匀的数字)。