JavaScript中的16位二进制算术

4

Javascript只有一种数字类型:64位浮点数。

使用Javascript,我需要实现一个哈希算法,该算法设计为使用16位无符号整数的C编写。

主要操作如下(伪代码):

uint16 n = 0;
string s = "abcd1234";

for (int i = 0; i < s.length; i += 1) {
    n ^= (n << 2) + (n >> 3) + s[i];
}

return n;

当使用uint16值时,这会产生一个结果;如果n是64位浮点数,则会产生不同的结果。
到目前为止,我对这个问题的最佳解决方案是将每个位运算的结果转换为<= 16位,使用类似于以下javascript函数的函数:
function uint16 (n) {
    return parseInt(n.toString(2).slice(-16), 2);
}

进行类似以下javascript代码的操作:

for (var i = 0; i < s.length; i +=1 ) {
    n ^= uint16(uint16(n << 2) + uint16(n >>> 3) + s.charCodeAt(i));
}

但我并不百分之百地确定这将总是产生正确的结果。

在JavaScript中,是否有一种标准的方法来模拟对数字值进行16位无符号位数操作?


在Javascript中,浮点数并不是唯一的数字类型 - 还有整数。任何对浮点数的位运算都会将数字向下舍入为整数。例如,3.5 << 1 == 610.9 | 0 == 10。然而,32位和16位整数的结果可能不同。@Amit提供了一种将数字转换为“16位”整数的方法,即通过修剪它来实现...但是您可能需要查看JS TypedArrays,例如Uint16Array。https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays - Aurel Bílý
2个回答

6

您可以使用按位与

它作用于32位整数,但是您可以只使用"and"和0xffff。

function uint16 (n) {
  return n & 0xFFFF;
}

此外,位移操作(<<>>>)也适用于32位整数,因此您只需要在赋值之前调用uint16函数即可。
for (var i = 0; i < s.length; i +=1 ) {
  n ^= uint16((n << 2) + (n >>> 3) + s.charCodeAt(i));
}

谢谢 - AND运算看起来是个好主意,但我不明白仅在最后修剪结果的做法如何奏效。我认为这就像在32位容器中处理16位值一样..如果使用>>>,是否会带入高阶位,而这些高阶位在真正的16位值中应该是0? - Alex McMillan
@AlexMcMillan - 是的,你是对的.. 你确实需要中间操作。 - Amit
1
另外提一下,如果你想要16位的有符号整数,可以使用(n << 16 >> 16),它将会对n的左侧16位进行符号扩展。 - mseddon

1

我怀疑 @Amit 的版本会更快执行,但这是我成功使用的一种解决方法:

//create a typed container, we'll work only in the first index.
const idx = 0;
const n = new Uint16Array(1);

for (int i = 0; i < s.length; i += 1) {
    n[idx] ^= (n[idx] << 2) + (n[idx] >> 3) + s[i];
}

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