我正在寻找一种在 JavaScript 中对 64 位整数执行按位 AND 的方法。
JavaScript 会将其所有双精度值转换为有符号的 32 位整数以执行按位运算(详情请点击此处)。
我正在寻找一种在 JavaScript 中对 64 位整数执行按位 AND 的方法。
JavaScript 会将其所有双精度值转换为有符号的 32 位整数以执行按位运算(详情请点击此处)。
Javascript 将所有数字表示为 64 位双精度 IEEE 754 浮点数(请参阅ECMAscript 规范,第 8.5 节。)所有高达 2^53 的正整数都可以精确编码。较大的整数会剪掉它们的最低有效位。这留下了一个问题,即如何在 Javascript 中表示 64 位整数——本机数字数据类型显然不能精确表示 64 位整数。
下面说明了这一点。尽管 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>
在 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
所以,你可以做什么?
如果您选择将 64 位整数表示为两个 32 位数字,那么应用按位 AND 就像对低位和高位 32 位“字”应用 2 个按位 AND 一样简单。
例如:
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);
让你:
ff00:ff0000
这是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;
}
现在可以使用新的 BigInt 内置数字类型来完成。BigInt 目前(2019 年 7 月)仅在某些浏览器中可用,详情请参见以下链接:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt
我已经在 Chrome 67 中使用 BigInts 测试了按位运算,并且可以确认它们在最多 64 位值的情况下按预期工作。
Javascript 不支持开箱即用的 64 位整数。这就是我最终做的:
Long
.Long
从低位和高位初始化一个新的64位注:下面工作的代码示例,你需要负载 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);
控制台输出:
2^3
00000000000000000000000000000000000000000000000000000000001000
2^3 + 2^63
00100000000000000000000000000000000000000000000000000000001000
2^3 & (2^3 + 2^63)
00000000000000000000000000000000000000000000000000000000001000
val1 和 val2 之间的相关性?
真的
Closure 库具有goog.math.Long
按位add()
方法。