如何在PHP中将字符串转换为64位整数哈希?

3

我需要对字符串进行64位整数哈希,用于类似哈希映射的操作。

据我所知,PHP没有原生的哈希功能可以返回64位整数?

我认为可以将sha1哈希的第一部分转换为整数。但是这样做性能不佳,转换也很棘手。

当然,如果能使用原生的PHP函数而无需安装,则最好不过了。


首先,您需要一个64位大小(或更低)的哈希来将其转换为64位(有符号)整数。您对哈希算法有偏好吗?还是这是您问题的一部分? - hakre
请参考这个相关问题,它应该很容易从Java转换到PHP:https://dev59.com/questions/nXI-5IYBdhLWcg3w0MDx - hakre
你可能已经考虑过了,但是使用字符串本身作为数组的键,并让PHP隐式地处理哈希怎么样? - Jon
@hakre:我更喜欢使用本地的PHP算法,所以也许可以用sha1?我已经尝试过那个算法了,与本地的sha1()相比,速度真的很慢。 - flori
@Jon:我想将它写入数据库,因此整数更适合。 - flori
6个回答

7

我尝试了很多次,特别是将一个完整的64位十六进制字符串转换为带符号的64位整数。现在我得出了以下结果:

function sha1_64bitInt($str) {
    $u = unpack('N2', sha1($str, true));
    return ($u[1] << 32) | $u[2];
}

这个性能在中等水平。比实现完整的哈希算法(例如SimpleHash或dbj2)要好得多,但比直接调用sha1()crc32慢得多。

如果有更好的解决方法来转换为64位整数,则可能在不破坏向后兼容性的情况下改进此函数(我希望如此)。


这个哈希函数是否能在64位哈希空间上均匀分布键? - tonix
1
@tonix 这是使用 SHA1 哈希的前 8 个字节。据说 SHA1 具有均匀分布。所以我会期望它,是的。 - flori

3

查看此页面以获取有关 md5 哈希的信息:

http://us.php.net/manual/en/function.md5.php

这将输出一个32个字符的十六进制字符串。每个十六进制字符表示4位数据。这意味着您需要16个十六进制字符(或MD5哈希值的一半)来生成64位。
然后,您可以使用hexdec将64位(16x4=64)从十六进制转换为整数。请注意,如果传递的比64位更多,则函数将溢出到浮点类型以尝试表示更大的数字。

http://php.net/hexdec

基本上

$stringToHash= "abcdefghijk...";
$hash = md5($stringToHash);
$substring = substr($hash, 0,16);
$finalInt = hexdec($substring);

这应该适用于您。(但我还没有测试过)


我尝试了类似的东西。一般的问题是hexdec()返回一个浮点数。在我看来,hexdec将十六进制值解释为无符号数。 - flori
你可以始终使用63位甚至60位... 它只会在前导位上填充0。 - Zak

0

据我理解,“64”表示该代码针对64位硬件进行了优化,但仍返回32位或128位哈希值。 - flori
一个很好的观点。但是这个算法非常简单,你可以自己实现它(在这个维基页面中搜索“64位finalizer”),或者只使用128位中的64位。保证非常快速,并且相对抗冲突。 - Nemo

0

我认为PHP不支持64位整数。有一个BigInteger类(非原生PHP)可供使用(如果您在Google上搜索得很好,就可以找到)。但它只是在内部使用字符串,并且非常复杂。


2
64位整数在64位硬件上,并且PHP安装正确时可以正常使用(我正在使用它们)。 - flori
1
实际上,如果您在64位平台上运行,PHP具有64位整数。 - Jim Mischel
是的,您需要在64位硬件上安装64位PHP。 - Pwnna

0

0
我编写了这个函数。它使用不同的crc32和crc32b来计算两个32位哈希值,然后将它们组合起来得到一个64位哈希值。最后将其转换为64位整数以保存在MySQL数据库中的无符号BIGINT字段中。
function hash64int($string)
{
    return $string ? hexdec(hash('crc32', $string) . hash('crc32b', $string)) : null;
}

在某些情况下,32位哈希值可能已经足够。因此,您可以使用此函数并将其保存在无符号INT字段中:

function hash32int($string)
{
    return $string ? hexdec(hash('crc32', $string)) : null;
}

我使用crc32是因为它比其他方法更快。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接