javascript IPアドレスを数値化するいくつかの方法で、効率に挑戦してみましょう

6752 ワード

まずIPアドレスとは何かを見てみましょう.
IPアドレスは32ビットのバイナリ数で、通常は4つの「8ビットバイナリ数」(つまり4バイト)に分割される.IPアドレスは通常「ポイント10進数」(a.b.c.d)の形式で表され、ここで、a,b,c,dはいずれも0~255の間の10進整数である.例:ポイント10進IPアドレス(100.4.5.6)は、実際には32ビット2進数(01100100.0000100.0000100.0000101.0000110)である.
IPアドレスを変換する理由:
点分十進法は記憶をよくするためだけで、コンピュータの演算には使えない.
データベースにIPアドレスとあるフィールドは一般的に整数に保存され、クエリーが容易になり、クエリーの速度を高めることができます.
JAvascriptで変換されるいくつかのスキーム:
まずIPアドレスの検証についてお話ししますが、
ここでは正規表現で検証し、次のようにします.
var REG =/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;

后ろのコードの中でREGを使うのはこれで、この正则の表现は少し长いですが、それを使って検证と分割を1歩しっかりと置くことができて、后ろの変换の时IPアドレスを分割するステップを省きました;
シナリオ1:8ビットごとに16進数文字に変換し、つなぎ合わせて整数に変換するIPアドレスが「.」分割後、各セグメントは8桁なので、ちょうど2桁の16進数に変換して、16進数の文字列をつなぎ合わせて、数字に変換すればOKです.
 
function ipToInt(IP){

    var xH = "",result = REG.exec(ip);

    if(!result) return -1;

    for (var i = 1; i <= 4; i++) {

        var h = parseInt(result[i]);

        xH += (h > 15 ? "" : "0") + h.toString(16);

    }

    return parseInt(xH, 16);

}

検証しないならかっこいい書き方に変えてもいいです.
function ipToInt(IP){

    return parseInt(IP.replace(/\d+\.?/ig,function(a){

        a = parseInt(a); 

        return (a > 15 ? "" : "0") + a.toString(16);

    }),16);

}

シナリオ2:IPアドレスを知った構造を直接計算すると,分割後の数字に相応の数を乗じて加算すればよいと考えるのは難しくない.
function ipToInt(IP){

    var xH = "",result = REG.exec(ip);

    if(!result) return -1;

    return (parseInt(result[1]) * 0x1000000 

        + parseInt(result[2]) * 0x10000 

        + parseInt(result[3]) * 0x100 

        + parseInt(result[4]));

}

シナリオ3:ビット別計算
直接覚えたほうがビットで計算したほうがいいですが、それはもっと速いのではないでしょうか.
function ipToInt(IP){

    var xH = "",result = REG.exec(ip);

    if(!result) return -1;

    return (parseInt(result[1]) << 24 

        | parseInt(result[2]) << 16

        | parseInt(result[3]) << 8

        | parseInt(result[4]));

}

読めない場合は、戻って2進法の授業を補ってくださいね.
上のビット演算は問題ないように見えますが、いくつかのIPアドレスを試してみると間違っています.最後に、IPの値が0 x 7 fffffffff(127.255.255.255.255)より大きいと負の数になります.JSはビット演算時に32ビットの整数として計算されていたため、本来は32ビットでしたが、一番左のビットがシンボルビットになりました.足りないのではないでしょうか.多くの学生がオーバーフローを発見した後、この安案を放棄したのではないでしょうか.あきらめるつもりだったときに考えてみたのですが、違いますね.記号ビットは0,1ではないでしょうか.「>>」の記号なし右シフト演算子があるのではないでしょうか.私は記号なし右シフト0ビットではだめです.
function ipToInt(IP){

    var xH = "",result = REG.exec(ip);

    if(!result) return -1;

    return (parseInt(result[1]) << 24 

        | parseInt(result[2]) << 16

        | parseInt(result[3]) << 8

        | parseInt(result[4]))>>>0;

}

テストの后はやはりOKで、幸いなことにIPアドレスは32ビットで、ちょうど良くて、さもなくばこの方案は放弃するしかありません.
シナリオ4:ビット単位、文字列の結合(純粋に盲目的な振り回されに属する)
function ipToInt(IP) {

    var xH = "",

    result = REG.exec(ip);

    if (!result) return - 1;

    var ip2 = "000000" + ((parseInt(result[2]) << 16) | (parseInt(result[3]) << 8) | parseInt(result[4])).toString(16);

    return parseInt(parseInt(result[1]).toString(16) + ip2.substr(ip2.length - 6), 16);

}

なぜこんな変な考えがあるのかと聞いているに違いないが、実は安位演算でシンボルビットの問題が発生し、あきらめたくないという考えが出てきた.
まとめ
理屈から言えば「案3」は最も効率的な方法であるはずだ.しかし、最後の100万回の演算テストでは、「シナリオ2」の効率と「シナリオ3」がほぼ同じであることが明らかになった.V 8のためだろうか. 
逆関数を添付します.
function intToIp(INT){

    if(INT < 0 || INT > 0xFFFFFFFF){

        throw ("The number is not normal!");

    }

    return (INT>>>24) + "." + (INT>>16 & 0xFF) + "." + (INT>>8 & 0xFF) + "." + (INT & 0xFF);

}

転載は出典http://www.cnblogs.com/whyoopを明記してください.ありがとうございます.