【问题标题】:Porting '&' operator from Java to Javascript: Overflow issues将“&”运算符从 Java 移植到 Javascript:溢出问题
【发布时间】:2012-10-04 20:28:02
【问题描述】:

考虑以下 JAVA 语句:

System.out.println(3232235776l & 0xFFFFFFFE);

输出为:3232235776


当我用 JavaScript 重写语句时:

console.log(3232235776 & 0xFFFFFFFE);

输出为:-1062731520


问。有没有办法解决 JavaScript 中的这种溢出问题并获得正确的输出?


为了简单起见,我没有发布我从 Java 转换的函数。这里是。请假设 ipToLong 和 longToIp 在 Java 和 JavaScript 中都是有效的黑盒(即,它们在 Java 和 JS 中正确地进行 ip 到 long int 的转换,反之亦然,经过 linted 和单元测试)。

取自这里:https://stackoverflow.com/a/5032908/504674

现在,有人可以帮我将下面的 Java 行正确地转换为 JavaScript 吗?
具体来说:long maskedBase = start & mask;.

要转换的完整函数:

public static List<String> range2cidrlist( String startIp, String endIp ) {
    int[] CIDR2MASK = new int[] { 0x00000000, 0x80000000,
        0xC0000000, 0xE0000000, 0xF0000000, 0xF8000000, 0xFC000000,
        0xFE000000, 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000,
        0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000,
        0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, 0xFFFFF800,
        0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0,
        0xFFFFFFE0, 0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE,
        0xFFFFFFFF
    };

    long start = ipToLong(startIp);
    long end = ipToLong(endIp);

    ArrayList<String> pairs = new ArrayList<String>();
    while ( end >= start ) {
        byte maxsize = 32;
        while ( maxsize > 0) {
            long mask = CIDR2MASK[maxsize -1];
            long maskedBase = start & mask;

            if ( maskedBase != start ) {
                break;
            }

            maxsize--;
        }
        double x = Math.log( end - start + 1) / Math.log( 2 );
        byte maxdiff = (byte)( 32 - Math.floor( x ) );
        if ( maxsize < maxdiff) {
            maxsize = maxdiff;
        }
        String ip = longToIp(start);
        pairs.add( ip + "/" + maxsize);
        start += Math.pow( 2, (32 - maxsize) );
    }
    return pairs;
}

【问题讨论】:

  • 一些背景知识:JavaScript 没有 int 或 long 类型,只有 Number 是 64 位浮点数(如 double)。问题是,按位运算是通过临时将其转换为 32 位 int 并使用它来完成的。
  • 我明白这一点,因此我要求解决方法。现在,这在 JavaScript 中真的不可能吗?
  • 有一些可用于 JavaScript 的“扩展”数学库。从语法上讲这是不可能的,但是通过使用这些库中的函数,您可以获得所需的结果。
  • 请给其中任何一个链接?
  • 或者,要去掉掩码

标签: java javascript numbers long-integer


【解决方案1】:

您可以减去它,而不是使用&amp; 删除您想要的位。

long n = 3232235776L;
System.out.println(n - (n & 1)); // instead of 1 you can use ~0xFFFFFFFE

在您的情况下,这不应该受到溢出的影响。

【讨论】:

  • 它在 JavaScript 中溢出。你的回答看起来与 Java 相关。
  • 该示例与问题中的 Java 相关,但操作也不应在 JavaScript 中溢出。
  • Q. Is there a way to work around this overflow in JavaScript and get the right output? 那是问题。
  • 哦,我明白了,是的。那为什么不把它放到答案中呢?然而,n &gt;&gt; 1 &lt;&lt; 1 也遭受了同样的转换。
  • @phant0m 我将(n - (n &amp; 1)) 转换为 JavaScript 作为读者练习。 ;)
【解决方案2】:

按位运算符将其操作数视为 32 位(零和一)的序列

says the Mozilla documentation.

您从浮点值开始,它被转换为 32 位值。但是因为太大,会溢出。

我建议您尝试以下方法:

var number = 3232235776;
if (number % 2 == 1) {
    number = number - 1;
}

当然,你可以写得更简洁,但也更神秘:

var number = 3232235776;
number = number - (number % 2);

对于正数和负数,这在语义上应该是等效的。

签名扩展

在 Java 中,0xFFFFFFFE 是一个代表-2 的 32 位整数,当它与一个 long 进行与运算时,它会转换为一个 64 位整数:0xFFFF_FFFF_FFFF_FFFE,所以这一切实际上都是清除最后一位,即向下舍入(下降,而不是趋近于零)。

我不确定这是否是您想要的。如果它是有意的,它可能不是我在我的代码库中想要的东西。

无符号扩展

这是等效的 JavaScript 代码,如果您希望在没有符号扩展的情况下发生这种情况:

var number = 3232235776;
if (number % 2 == 1) {
    number = number - 1;
}
number = number % 0x100000000; // That's 8 zeroes, i.e. keep the last 4 bytes

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-04
    • 1970-01-01
    • 1970-01-01
    • 2016-05-25
    • 2017-12-21
    • 2010-12-24
    相关资源
    最近更新 更多