如何在 javascript 中对长度超过 32 位的变量进行按位 AND 操作?

问题描述 投票:0回答:6

我在 javascript 中有 2 个数字,我想对它们进行位和。它们都是 33bit 长

在 C# 中:

 ((4294967296 & 4294967296 )==0) is false

但是在 JavaScript 中:

 ((4294967296 & 4294967296 )==0) is true

4294967296 是((长)1)<< 32

据我了解,这是因为javascript在执行按位运算时将值转换为int32。

我该如何解决这个问题? 关于如何替换位以及使用一组其他数学运算以免丢失位有什么建议吗?

javascript 64-bit bit-manipulation
6个回答
15
投票

这是一个用于任意大整数的有趣函数:

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位按位运算。


5
投票

您可以将每个变量拆分为 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));

1
投票

Javascript 中有多个 BigInteger 库,但目前没有一个提供您需要的按位运算。如果您有动力并且确实需要该功能,您可以修改其中一个库并添加一种方法来执行此操作。他们已经提供了一个很好的代码库来处理大量的问题。

您可以在这个问题中找到 Javascript 中的 BigInteger 库的列表:

巨大的整数JavaScript库


1
投票

最简单的按位与,最多可达到 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)
}

0
投票

今天遇到这个问题,这就是我想到的:

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);
}

希望这可以帮助遇到此问题的其他人。


0
投票

这里的几个答案不太正确。这应该是快速且正确的:

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.