移植'&'从Java到Javascript的运算符:溢出问题

时间:2012-10-04 11:13:15

标签: java javascript numbers long-integer

考虑以下 JAVA 声明:

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

输出为: 3232235776


当我在 JavaScript

中重新编写语句时
console.log(3232235776 & 0xFFFFFFFE);

输出为: -1062731520


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


为了简单起见,我没有发布我从Java转换的函数。这里是。请假设ipToLonglongToIp作为Java和JavaScript中的工作黑盒子(即他们正确执行ip到long int转换,反之亦然,在Java和JS中,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;
}

2 个答案:

答案 0 :(得分:3)

您可以减去它,而不是使用&删除所需的位。

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

这不应该在您的情况下出现溢出。

答案 1 :(得分:1)

  

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

says the Mozilla documentation.

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

我建议您尝试以下方法:

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

当然,你可以更简洁地写出来,但也更神秘:

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

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

签署扩展名

在Java中,0xFFFFFFFE是一个32位整数,表示-2当使用long进行AND运算时,它会被转换为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