【问题标题】:How to do bitwise AND in javascript on variables that are longer than 32 bit?如何在javascript中对超过32位的变量进行按位与?
【发布时间】:2010-09-03 16:29:29
【问题描述】:

我在 javascript 中有 2 个数字,我想咬一下。它们都是 33 位长

在 C# 中:

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

但在 javascript 中:

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

4294967296 是 ((long)1)

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

我该如何解决这个问题? 关于如何替换位和使用一组其他数学运算以不丢失位的任何建议?

【问题讨论】:

标签: javascript 64-bit bit-manipulation


【解决方案1】:

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

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

【讨论】:

  • 太棒了!你有按位的功能吗?
  • 在我的脑海中,我认为您只需将单个 &amp; 更改为 |var rs = (mask &amp; val1) &amp; (mask &amp; val2);var rs = (mask &amp; val1) | (mask &amp; val2);
  • 很棒的功能,但我无法使用 32 位或更多位。
  • 谢谢,但功能没有像宣传的那样工作不值得投反对票吗?哪些操作不起作用(例如 val1val2 的值,以及函数的结果,以及您期望从函数中获得的值)?
  • @palswim,了不起的解决方案
【解决方案2】:

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

【讨论】:

  • 它不起作用:bitwiseAnd_53bit(114287881752716, 0x0fffffffff0000)
【解决方案3】:

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

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

Huge Integer JavaScript Library

【讨论】:

    【解决方案4】:

    您可以将每个 var 拆分为 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 不支持数字中的真正 64 位值,最大 53 位。因为它使用 float64 (double) 来操作任何整数。另见stackoverflow.com/a/45425630/1848217
    • 这对于 -2^32 左右的值仍然失败(但不完全是 -2^32)。我找不到解决方案。舍入 hi 部分仅适用于少数值。 hi 倾向于保持在 -1 而应该是 -2 什么的。
    • 我用javascript做了一个快速测试,它在a=114287881752716 b=0x0fffffffff0000上不起作用
    【解决方案5】:

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

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

    希望这对遇到此问题的其他人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多