我在 javascript 中有 2 个数字,我想对它们进行位和。它们都是 33bit 长
在 C# 中:
((4294967296 & 4294967296 )==0) is false
但是在 JavaScript 中:
((4294967296 & 4294967296 )==0) is true
4294967296 是((长)1)<< 32
据我了解,这是因为javascript在执行按位运算时将值转换为int32。
我该如何解决这个问题? 关于如何替换位以及使用一组其他数学运算以免丢失位有什么建议吗?
这是一个用于任意大整数的有趣函数:
function BitwiseAndLarge(val1, val2) {
var shift = 0, result = 0;
var mask = ~((~0) << 30); // Gives us a bit mask like 01111..1 (30 ones)
var divisor = 1 << 30; // To work with the bit mask, we need to clear bits at a time
while( (val1 != 0) && (val2 != 0) ) {
var rs = (mask & val1) & (mask & val2);
val1 = Math.floor(val1 / divisor); // val1 >>> 30
val2 = Math.floor(val2 / divisor); // val2 >>> 30
for(var i = shift++; i--;) {
rs *= divisor; // rs << 30
}
result += rs;
}
return result;
}
假设系统至少可以正确处理30位按位运算。
您可以将每个变量拆分为 2 个 32 位值(如高位字和低位字),然后对两对进行按位运算。
下面的脚本作为 Windows .js 脚本运行。对于 Web,您可以将 WScript.Echo() 替换为alert()。
var a = 4294967296;
var b = 4294967296;
var w = 4294967296; // 2^32
var aHI = a / w;
var aLO = a % w;
var bHI = b / w;
var bLO = b % w;
WScript.Echo((aHI & bHI) * w + (aLO & bLO));
Javascript 中有多个 BigInteger 库,但目前没有一个提供您需要的按位运算。如果您有动力并且确实需要该功能,您可以修改其中一个库并添加一种方法来执行此操作。他们已经提供了一个很好的代码库来处理大量的问题。
您可以在这个问题中找到 Javascript 中的 BigInteger 库的列表:
最简单的按位与,最多可达到 JavaScript 的最大数量
由于内部原因,JavaScript 的最大整数值为 2^53(它是双精度浮点数)。如果您需要更多,可以使用一些很好的库来处理大整数。
2^53 是 9,007,199,254,740,992,或大约 9,000 万亿(约 9 万亿)。
// Works with values up to 2^53
function bitwiseAnd_53bit(value1, value2) {
const maxInt32Bits = 4294967296; // 2^32
const value1_highBits = value1 / maxInt32Bits;
const value1_lowBits = value1 % maxInt32Bits;
const value2_highBits = value2 / maxInt32Bits;
const value2_lowBits = value2 % maxInt32Bits;
return (value1_highBits & value2_highBits) * maxInt32Bits + (value1_lowBits & value2_lowBits)
}
今天遇到这个问题,这就是我想到的:
function bitwiseAnd(firstNumber, secondNumber) {
let // convert the numbers to binary strings
firstBitArray = (firstNumber).toString(2),
secondBitArray = (secondNumber).toString(2),
resultedBitArray = [],
// get the length of the largest number
maxLength = Math.max(firstBitArray.length, secondBitArray.length);
//add zero fill ahead in case the binary strings have different lengths
//so we can have strings equal in length and compare bit by bit
firstBitArray = firstBitArray.padStart(maxLength,'0');
secondBitArray = secondBitArray.padStart(maxLength,'0');
// bit by bit comparison
for(let i = 0; i < maxLength; i++) {
resultedBitArray.push(parseInt(firstBitArray[i]) && secondBitArray[i]);
}
//concat the result array back to a string and parse the binary string back to an integer
return parseInt(resultedBitArray.join(''),2);
}
希望这可以帮助遇到此问题的其他人。
这里的几个答案不太正确。这应该是快速且正确的:
function and(x, y) {
const max = 0x100000000;
const highx = Math.floor(x / max);
const highy = Math.floor(y / max);
const lowx = x % max;
const lowy = y % max
let low = lowx & lowy;
if (low < 0) { low += max; }
let high = highx & highy;
if (high < 0) { high += max; }
return high * max + low;
}
function or(x, y) {
const max = 0x100000000;
const highx = Math.floor(x / max);
const highy = Math.floor(y / max);
const lowx = x % max;
const lowy = y % max
let low = lowx | lowy;
if (low < 0) { low += max; }
let high = highx | highy;
if (high < 0) { high += max; }
return high * max + low;
}