C#和Javascript位运算符之间的不一致性

3

给定以下代码:

uint HASHTABLE = 1917507215;
for (uint i = 5; i != 0; i--)
        {
            HASHTABLE = (HASHTABLE ^ ((HASHTABLE << 10 ^ HASHTABLE) << 9 ^ HASHTABLE) << 5) & 0x7fffffff ^ (((HASHTABLE << 7 ^ HASHTABLE) << 10 ^ HASHTABLE) << 9 ^ HASHTABLE) << 5;
            HASHTABLE = HASHTABLE >> 1 | (HASHTABLE & 1) << 0x1f;
        }

我正在尝试将这段代码转换为JavaScript,但我注意到计算中存在不一致性。 在C#中,循环完成后HASHTABLE的值为1871861428, 而在JavaScript中,该值为-275622220。

我怀疑问题出在C#中该值应该是无符号的事实上。 此外,JavaScript可以执行最多32位的位运算符。

这就是为什么我尝试继续使用Long库(https://www.npmjs.com/package/long

因此,我已将我的HASHTABLE值设置为Long.fromValue(HASHTABLE, true),并使用Long进行操作,如下所示:

hashTable = Long.fromValue(hashTable, true);
for (let i = 5; i != 0; i--) {
    hashTable = hashTable.xor(
        hashTable.shiftLeft(10).xor(hashTable).shiftLeft(9).xor(hashTable).shiftLeft(5)
      ).and(0x7fffffff).xor(
        hashTable.shiftLeft(7).xor(hashTable).shiftLeft(10).xor(hashTable).shiftLeft(9).xor(hashTable).shiftLeft(5)
    );
    hashTable = hashTable.shiftRight(1).or(hashTable.and(1).shiftLeft(0x1f));
}
hashTable = hashTable.toInt();

然而,即使使用Long,在Javascript中我的HASHTABLE值仍将是4019345076。

基本上,在Javascript中我会得到0xEF9256B4,而在C#中我会正确地得到0x6F9256B4,区别在于JavaScript中设置了第32位(最高有效位),而在C#中没有。

我在这里缺少什么,为什么即使使用Long库,在JavaScript和C#之间存在这种不一致性?


1
你尝试过使用.shiftRightUnsigned()而不是普通的.shiftRight()吗? - Pointy
1个回答

3

请查看无符号右移运算符 >>>

let HASHTABLE = 1917507215;
for (let i = 5; i != 0; i--) {
  HASHTABLE = (HASHTABLE ^ ((HASHTABLE << 10 ^ HASHTABLE) << 9 ^ HASHTABLE) << 5) & 0x7fffffff ^ (((HASHTABLE << 7 ^ HASHTABLE) << 10 ^ HASHTABLE) << 9 ^ HASHTABLE) << 5;
  HASHTABLE = HASHTABLE >>> 1 | (HASHTABLE & 1) << 0x1f;
}
console.log(HASHTABLE);


2
谢谢,这确实解决了问题,现在我不再需要使用Long库了。我完全忘记了>>>运算符。 - Wilhelm Sorban

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