在JavaScript中使用具有大量数字的按位运算符

时间:2019-06-21 11:03:09

标签: javascript compression long-integer

我正在编写此Microsoft string decoding algorithm的Javascript版本,并且大量失败。这似乎是由于上浆(整数/长整数)问题。如果我逐步执行C#中的代码,我会发现JS实现在此行上失败

n |= (b & 31) << k;

当值是(并且C#结果为240518168576)时,会发生这种情况

(39 & 31) << 35

如果我在C#中使用这些值,并且bint,则可以复制JS问题。而且,如果我将b设置为long,它将正常工作。

因此,我检查了一个JS数字的最大大小,并将其与C#长的result

进行了比较。
240518168576 < Number.MAX_SAFE_INTEGER = true

所以..我可以看到正在发生某种数字大小问题,但不知道如何强制JS将这个数字视为长数字。

完整的JS代码:

private getPointsFromEncodedString(encodedLine: string): number[][] {

    const EncodingString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";

    var points: number[][] = [];

    if (!encodedLine) {
        return points;
    }

    var index = 0;
    var xsum = 0;
    var ysum = 0;

    while (index < encodedLine.length) {
        var n = 0;
        var k = 0;

        debugger;

        while (true) {
            if (index >= encodedLine.length) {
                return points;
            }

            var b = EncodingString.indexOf(encodedLine[index++]);

            if (b == -1) {
                return points;
            }

            n |= (b & 31) << k;
            k += 5;
            if (b < 32) {
                break;
            }
        }

        var diagonal = ((Math.sqrt(8 * n + 5) - 1) / 2);

        n -= diagonal * (diagonal + 1) / 2;

        var ny = n;
        var nx = diagonal - ny;

        nx = (nx >> 1) ^ -(nx & 1);
        ny = (ny >> 1) ^ -(ny & 1);

        xsum += nx;
        ysum += ny;

        points.push([ysum * 0.000001, xsum * 0.000001]);
    }

    console.log(points);

    return points;
}

预期的输入输出:

编码字符串

  

qkoo7v4q-lmB0471BiuuNmo30B

解码点:

  • 35.89431,-110.72522
  • 35.89393,-110.72578
  • 35.89374,-110.72606
  • 35.89337,-110.72662

1 个答案:

答案 0 :(得分:3)

  

按位运算符将其操作数视为32位序列   (零和一),而不是十进制,十六进制或八进制   数字。例如,十进制数字9有一个二进制   表示1001。按位运算符在   这样的二进制表示形式,但是它们返回标准的JavaScript   数值。

(39 & 31) << 35尝试在只有32位时移位35位

Bitwise Operators

要解决此问题,您可以使用BigInt执行这些操作,然后将其向下转换回Number

Number((39n & 31n) << 35n)

您可以尝试以下方法:

function getPointsFromEncodedString(encodedLine) {

    const EncodingString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";

    var points = [];

    if (!encodedLine) {
        return points;
    }

    var index = 0;
    var xsum = 0;
    var ysum = 0;

    while (index < encodedLine.length) {
        var n = 0n;
        var k = 0n;


        while (true) {
            if (index >= encodedLine.length) {
                return points;
            }

            var b = EncodingString.indexOf(encodedLine[index++]);

            if (b === -1) {
                return points;
            }

            n |= (b & 31n) << k;
            k += 5n;
            if (b < 32n) {
                break;
            }
        }

        var diagonal = ((Math.sqrt(8 * Number(n) + 5) - 1) / 2);

        n -= diagonal * (diagonal + 1) / 2;

        var ny = n;
        var nx = diagonal - ny;

        nx = (nx >> 1) ^ -(nx & 1);
        ny = (ny >> 1) ^ -(ny & 1);

        xsum += Number(nx);
        ysum += Number(ny);

        points.push([ysum * 0.000001, xsum * 0.000001]);
    }

    console.log(points);

    return points;
}