【发布时间】:2020-09-01 23:32:30
【问题描述】:
我在搞乱哈希函数,移植一些经典,如 murmur 或 fnv 系列,并创建我自己的,真的很有趣。我知道 js 并不是一个理想的环境,但无论如何。
我遇到的最大障碍是 js 对大多数算术都使用双精度数。我见过的几乎每一个散列函数都通过乘法来利用整数溢出。例如,我将 7 的输入乘以 0x5bd1e995 之类的大素数,这种乘法将小输入的重要性放大到结果的每一位,这对于散列函数来说非常简洁。
不幸的是,当使用双精度进行数学运算时,这完全是平的,因为双精度不会像整数那样溢出(保留最低有效位),而是尝试保留结果的大小(保留最高有效位)并且与几乎所有哈希函数的设计。
我发现解决这个问题的几种方法是
- 在乘法之前对输入取模,以确保结果不超过 Number.MAX_SAFE_INTEGER
- 将输入拆分为两个 16 位值并重新组合后进行乘法运算
- 根据输入使用各种幻数,以确保我保持在整数的双精度范围内
问题是,这些都不是快速的,并且会将性能切成碎片。那么,提问时间:如果乘法几乎肯定会超过 Number.MAX_SAFE_INTEGER,是否有一种性能良好的方法来模拟 js 中的整数溢出行为?
【问题讨论】:
-
你的意思是像c类型的int乘法吗?它只是截断高位并在溢出期间保留低位 32。如果你想看看
Math.imul。 -
我猜BigInt 在您的可能但缓慢的选项列表中排名第四?
-
@HanYolo 没错,正在调查!
-
@AhmedFasih 是的,BigInt 在技术上是一种选择,但比其他所有方法加起来都慢。
-
@zero298 问题是,一旦你从一个类型化的数字数组中获取一个值,它就会变成一个普通的 JavaScript 数字。
标签: javascript algorithm integer-overflow