【问题标题】:Hash function w/ PHP integer overflow带有 PHP 整数溢出的哈希函数
【发布时间】:2011-06-04 20:48:02
【问题描述】:

我在这里查看了很多关于“PHP 整数溢出”的问题,但我找不到任何可以回答我的具体问题的问题,所以我希望我没有错过现有的答案。

我想使用 PHP 中的 djb2 hash 函数将键散列成类似分片标识符(SimpleDB 的域索引)的东西。它溢出了无符号长整数,所以我不能在直接的 PHP 中做同样的事情,因为 PHP 的原生整数是 32 位有符号的。

所以我尝试了 PHP 的 bclibgmp 数学扩展,它们允许任意长度,并且它们解决了符号/比例问题,但它们使整数“太大” - 即它们不会溢出。

使用 GMP 尤其有效并且似乎给出了一致的结果,但显然比在 C 中慢一个数量级(0m0.017s 与 0m0.002s)。我不知道这是否仅仅是因为它是 PHP vs C,或者如果我能让它溢出,它在 PHP 中是否会明显更快。我宁愿测试并找出答案,但我找不到实现这一目标的方法。

那么,有没有办法在 PHP 中强制达到 ULONG 最大值?我可能必须将 C 函数包装在 PHP 扩展中吗?或者,考虑到我只打算散列短键(可能是 64 个字符或更少),这会带来严重的收益递减吗?

【问题讨论】:

  • 这种故意溢出仅仅是为了消除对某些模运算的需要吗?如果是这样,移位和减法/否定的组合不能有帮助吗?我在想一些在概念上类似于你自己的 2 的补码的东西
  • 我一直认为哈希期间的溢出是允许/预期的,但并没有使任何事情变得更快。在这种情况下,执行的操作,即位移和加法,对大小不敏感(或不显着)。因此,我不认为缺乏溢出是性能的一个重要因素。 PHP w/GMP 解决方案比什么慢十倍?
  • 你好乔恩,谢谢。模数发生在乘法溢出发生之后。 PHP/GMP 比 C 中的相同例程慢十倍 - 我不确定这是因为在 GMP 中使用了非常大的数字而不是仅仅允许溢出,还是因为执行中的其他内容PHP.

标签: php hash integer overflow


【解决方案1】:

为什么您认为这些哈希函数需要超过 32 位? long 类型不能保证是那个大小,它们只是 >= 32 位。在我的 32 位平台上,long 始终是 32 位。

我认为,您链接到的那些注释是在 64 位不像现在那么流行的时候编写的,并且也是在 long long 类型(即使在 32 位平台上也是 >= 64 位)被引入之前编写的,所以作者只是使用了当时最大的类型。

“djb2”散列只是散列函数的另一种变体,几乎类似于线性同余生成器,并且早已为人所知。显式模运算被替换为溢出,实际上是“modulo 2^(sizeof long)”。如果编译为 C 语言,这可能(尽管不确定)对性能有好处,但对哈希质量可能不太好。而且它在 PHP 中没有意义,因为该数字将被提升为 double 并增长为无穷大。

我建议将散列算法与通常的 PHP 整数一起使用,但通过添加显式模数和除数来改进散列,除数是小于 PHP_INT_MAX 的素数(您是否检查过 PHP 的 64 位构建的限制,顺便一提?)。也许,必须更改乘数 (33) 以使用必须散列的字符串获得更好的散列分布。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-27
    • 1970-01-01
    • 1970-01-01
    • 2016-12-22
    • 1970-01-01
    • 2011-04-10
    • 2014-07-01
    相关资源
    最近更新 更多