在64位整数的Javascript中按位AND

Tob*_*ede 29 javascript 64-bit integer bit-manipulation

我正在寻找一种在JavaScript中对64位整数执行按位AND的方法.

JavaScript会将其所有双精度值转换为带符号的32位整数,以执行按位运算(详情请参见此处).

Ore*_*ner 31

Javascript将所有数字表示为64位双精度IEEE 754浮点数(请参阅ECMAscript规范,第8.5节.)可以精确编码所有高达2 ^ 53的正整数.较大的整数将其最不重要的位削减.这就留下了如何在Javascript中表示64位整数的问题 - 原生数字数据类型显然不能精确地表示64位int.

以下说明了这一点.虽然javascript 似乎能够解析表示64位数字的十六进制数字,但基础数字表示不能保存64位.在浏览器中尝试以下操作:

<html>
  <head>
    <script language="javascript">
      function showPrecisionLimits() {
        document.getElementById("r50").innerHTML = 0x0004000000000001 - 0x0004000000000000;
        document.getElementById("r51").innerHTML = 0x0008000000000001 - 0x0008000000000000;
        document.getElementById("r52").innerHTML = 0x0010000000000001 - 0x0010000000000000;
        document.getElementById("r53").innerHTML = 0x0020000000000001 - 0x0020000000000000;
        document.getElementById("r54").innerHTML = 0x0040000000000001 - 0x0040000000000000;
      }
    </script>
  </head>
  <body onload="showPrecisionLimits()">
    <p>(2^50+1) - (2^50) = <span id="r50"></span></p>
    <p>(2^51+1) - (2^51) = <span id="r51"></span></p>
    <p>(2^52+1) - (2^52) = <span id="r52"></span></p>
    <p>(2^53+1) - (2^53) = <span id="r53"></span></p>
    <p>(2^54+1) - (2^54) = <span id="r54"></span></p>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

在Firefox,Chrome和IE中,我得到以下内容.如果数字以完整的64位荣耀存储,那么对于所有的减法,结果应该是1.相反,你可以看到2 ^ 53 + 1和2 ^ 53之间的差异是如何丢失的.

(2^50+1) - (2^50) = 1
(2^51+1) - (2^51) = 1
(2^52+1) - (2^52) = 1
(2^53+1) - (2^53) = 0
(2^54+1) - (2^54) = 0
Run Code Online (Sandbox Code Playgroud)

所以,你可以做什么?

如果您选择将64位整数表示为两个32位数字,则应用按位AND就像将2位AND位应用于低位和高位32位"字"一样简单.

例如:

var a = [ 0x0000ffff, 0xffff0000 ];
var b = [ 0x00ffff00, 0x00ffff00 ];
var c = [ a[0] & b[0], a[1] & b[1] ];

document.body.innerHTML = c[0].toString(16) + ":" + c[1].toString(16);
Run Code Online (Sandbox Code Playgroud)

得到你:

ff00:ff0000
Run Code Online (Sandbox Code Playgroud)


And*_*rey 11

这是AND int64数字的代码,您可以用其他按位运算替换AND

function and(v1, v2) {
    var hi = 0x80000000;
    var low = 0x7fffffff;
    var hi1 = ~~(v1 / hi);
    var hi2 = ~~(v2 / hi);
    var low1 = v1 & low;
    var low2 = v2 & low;
    var h = hi1 & hi2;
    var l = low1 & low2;
    return h*hi + l;
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,要使用其他按位运算,您需要替换“h”和“l”表达式中的“&amp;”。 (3认同)

小智 9

现在可以使用新的 BigInt 内置数字类型来完成。BigInt 目前(2019 年 7 月)仅在某些浏览器中可用,详情请参见以下链接:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt

我已经在 Chrome 67 中使用 BigInts 测试了按位运算,并且可以确认它们在最多 64 位值的情况下按预期工作。


bou*_*nav 7

Javascript不支持开箱即用的64位整数.这就是我最终做的事情:

  1. 在github上找到long.js,一个自包含的Long实现.
  2. 将表示64位数的字符串值转换为a Long.
  3. 提取高32位值和低32位值
  4. 做32位按位高之间低位,分别
  5. Long从低位和高位初始化一个新的64 位
  6. 如果数字> 0,则两个数字之间存在相关性

注意:对于下面的代码示例工作,你需要加载 long.js.

// Handy to output leading zeros to make it easier to compare the bits when outputting to the console
function zeroPad(num, places){
    var zero = places - num.length + 1;
  return Array(+(zero > 0 && zero)).join('0') + num;
}

// 2^3 = 8
var val1 = Long.fromString('8', 10);
var val1High = val1.getHighBitsUnsigned();
var val1Low = val1.getLowBitsUnsigned();

// 2^61 = 2305843009213693960
var val2 = Long.fromString('2305843009213693960', 10);
var val2High = val2.getHighBitsUnsigned();
var val2Low = val2.getLowBitsUnsigned();

console.log('2^3 & (2^3 + 2^63)')
console.log(zeroPad(val1.toString(2), 64));
console.log(zeroPad(val2.toString(2), 64));

var bitwiseAndResult = Long.fromBits(val1Low & val2Low, val1High & val2High, true);

console.log(bitwiseAndResult);
console.log(zeroPad(bitwiseAndResult.toString(2), 64));
console.log('Correlation betwen val1 and val2 ?');
console.log(bitwiseAndResult > 0);
Run Code Online (Sandbox Code Playgroud)

控制台输出:

2 ^ 3

0000000000000000000000000000000000000000000000000000000000001000

2 ^ 3 + 2 ^ 63

0010000000000000000000000000000000000000000000000000000000001000

2 ^ 3&(2 ^ 3 + 2 ^ 63)

0000000000000000000000000000000000000000000000000000000000001000

val1和val2之间的相关性?

真正