0

次のJAVAステートメントを検討してください。

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

出力は次のとおりです。3232235776


JavaScriptでステートメントを書き直すと、次のようになります。

console.log(3232235776 & 0xFFFFFFFE);

出力は次のとおりです: -1062731520


Q. JavaScript でこのオーバーフローを回避し、正しい出力を得る方法はありますか?


簡単にするために、Java から変換した関数は投稿しませんでした。ここにあります。Java と JavaScript の両方でブラックボックスが動作していると仮定ipToLongしてくださいlongToIp(つまり、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;
}
4

2 に答える 2

3

必要なビットを削除するために使用する代わりに&、それを減算することができます。

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

あなたの場合、これはオーバーフローに悩まされるべきではありません。

于 2012-10-04T11:23:20.553 に答える
1

ビット演算子は、オペランドを32ビットのシーケンス(0と1)として扱います。

Mozillaのドキュメントは言います。

浮動小数点値から始めて、32ビット値に変換します。でも大きすぎるのであふれます。

代わりに次のことを試してみることをお勧めします。

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

もちろん、これをより簡潔に書くこともできますが、より不可解なこともできます。

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

これは、正の数と負の数の両方で意味的に同等である必要があります。

符号拡張

Javaでは、これをlongとAND演算すると、64ビット整数に変換されることを0xFFFFFFFE表す32ビット整数です。したがって、これが効果的に行うのは、最後のビットをクリアすること、つまり切り捨て(ゼロに向かってではなく切り捨て)だけです。-20xFFFF_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
于 2012-10-04T11:31:38.867 に答える