【发布时间】:2019-07-30 20:20:37
【问题描述】:
我需要将哈希函数从 JavaScript 转换为 Python。
函数如下:
function getIndex(string) {
var length = 27;
string = string.toLowerCase();
var hash = 0;
for (var i = 0; i < string.length; i++) {
hash = string.charCodeAt(i) + (hash << 6) + (hash << 16) - hash;
}
var index = Math.abs(hash % length);
return index;
}
console.log(getIndex(window.prompt("Enter a string to hash")));
此功能是 Objectively Correct™。它本身就是完美。我无法改变它,我只需要重新创建它。无论它输出什么,我的 Python 脚本也必须输出。
但是 - 我遇到了几个问题,我认为这与两种语言处理有符号整数的方式有关。
JS 位运算符将其操作数视为 32 位序列。然而,Python 没有位限制的概念,只是像一个绝对的疯子一样继续前进。我认为这是两种语言之间的一个相关区别。
我可以通过使用hash & 0xFFFFFFFF 将hash 屏蔽为32 位来限制Python 中hash 的长度。
如果0x7FFFFFFF 高于0x7FFFFFFF,我也可以用hash = hash ^ 0xFFFFFFFF(或hash = ~hash - 他们似乎都做同样的事情)来否定hash。我相信这会模拟负数。
我使用名为t 的函数将这两个限制应用于哈希。
到目前为止,这是我的 Python 代码:
def nickColor(string):
length = 27
def t(x):
x = x & 0xFFFFFFFF
if x > 0x7FFFFFFF:
x = x ^ 0xFFFFFFFF
return x
string = string.lower()
hash = t(0)
for letter in string:
hash = t(hash)
hash = t(t(ord(letter)) + t(hash << 6) + t(hash << 16) - t(hash))
index = hash % length
return index
它似乎一直有效,直到哈希需要变为负数,此时两个脚本出现分歧。这通常发生在字符串中大约 4 个字母。
我假设我的问题在于在 Python 中重新创建 JS 负数。我该如何告别这个问题?
【问题讨论】:
-
JavaScript 中的所有数字都是 64 位(双精度)浮点数,但 bitwise operators 将它们的操作数视为 32 位序列。
-
@Andreas - 谢谢你的信息,我不知道。
-
这些字符串能得到多长时间?
-
x ^ 0xFFFFFFFF不会否定该值,而是将其反转。差值是 1 个错误。
标签: python-3.x hash integer binary-operators