【问题标题】:How to get a 64 bit integer hash from a string in PHP?如何从 PHP 中的字符串中获取 64 位整数哈希?
【发布时间】:2011-09-12 20:49:35
【问题描述】:

我需要字符串的 64 位整数散列来用于散列映射之类的东西。

在我看来,似乎没有可以返回 64 位整数的原生 PHP 哈希功能?

我认为可以获取 sha1 哈希的第一部分并将其转换为整数。但是,这不会带来最佳性能,而且转换似乎很棘手。

当然最好不用安装就使用原生 PHP 函数。

【问题讨论】:

  • 首先,您需要一个 64BIT 大小(或更低)的散列来将其转换为 64BIT(有符号)整数。您是否偏爱散列算法,或者这是您问题的一部分?
  • 请看这个相关的问题,应该很容易从 Java 转换成 PHP:stackoverflow.com/questions/1660501/…
  • 您可能已经考虑过了,但是使用字符串本身作为数组的键并让 PHP 隐式处理散列呢?
  • @hakre:我更喜欢原生 PHP 算法,所以可能是 sha1?我已经尝试过该算法,与本机 sha1() 相比,它真的很慢
  • @Jon:我想把它写进数据库,所以整数更适合。

标签: php algorithm hash 64-bit integer


【解决方案1】:

我尝试了很多,尤其是将完整的 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 这是使用 SHA1 哈希的前 8 个字节。据说SHA1具有均匀分布。所以我会期待它,是的。
【解决方案2】:

有关 md5 哈希的信息,请参阅此页面:

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

这将输出一个 32 字符的十六进制字符串。每个十六进制字符代表 4 位数据。这意味着您需要 16 个十六进制字符(或 md5 哈希的一半)来生成 64 位。

然后您可以使用 hexdec 将 64 位 (16x4=64) 从 hex 转换为 int。请注意,如果您传递超过 64 位,该函数将溢出到浮点类型以尝试表示更大的数字

http://php.net/hexdec

基本上

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

这应该适合你。 (但我没有测试过)。

【讨论】:

  • 我尝试了类似的方法。一般的问题是 hexdec() 返回一个浮点数。在我看来,hexdec 将十六进制值解释为无符号。
  • 你总是可以只使用 63 甚至 60 位...它只会 0 填充前导位
【解决方案3】:

如果没有人有更好的主意,您可以修改 murmurhash_php 以非常轻松地调用 64 位版本的 MurmurHash3

【讨论】:

  • 据我了解,这些“64”表示代码针对 64 位硬件进行了优化,但仍返回 32 或 128 位哈希。
  • 一个公平的观点。但是该算法非常简单,您可以自己实现它(在this wiki page 中搜索“64 位终结器”)或只使用 128 位中的 64 位。保证速度非常快并且可以合理地抵抗碰撞。
【解决方案4】:

我认为 PHP 不支持 64 位整数。你可以使用一个 BigInteger 类(不是原生 PHP)(如果你用谷歌搜索的话)。但它只是在内部使用字符串,而且非常复杂。

【讨论】:

  • 当您在 64 位硬件上并且 PHP 以正确的方式安装时,64 位整数正在工作(我正在使用它们)。
  • 其实,如果你在 64 位平台上运行,PHP 有一个 64 位整数。
  • 是的,你需要在 64 位硬件上安装 64 位 PHP
【解决方案5】:

有关 CRC64 实施,请参阅 http://php.net/manual/ru/function.crc32.php#111699

【讨论】:

    【解决方案6】:

    我写了这个函数。它使用不同的 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,因为它比其他的固定。

    【讨论】:

      猜你喜欢
      • 2013-08-28
      • 2012-02-07
      • 2018-09-01
      • 2016-01-29
      • 2017-05-28
      • 1970-01-01
      • 2015-04-26
      • 1970-01-01
      • 2014-12-14
      相关资源
      最近更新 更多