javascript把IP地址轉為數值幾種方案,來挑戰一下效率吧

來源:互聯網
上載者:User
文章目錄
  • 為什麼要轉化IP地址:
先看看什麼是IP地址:

IP地址是一個32位的位元,通常被分割為4個“8位位元”(也就是4個位元組)。IP地址通常用“點分十進位”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之間的十進位整數。例:點分十進IP地址(100.4.5.6),實際上是32位位元(01100100.00000100.00000101.00000110)。

為什麼要轉化IP地址:

點分十進位標記法只是為了讓人好記憶,並不能用於電腦運算;

資料庫中跟IP地址有的欄位一般都會存成整數,這樣便於查詢,也可以提高了查詢速度;

javascript中轉換的幾種方案:

首先說一下IP地址的驗證,

這裡就用Regex驗證的方式,運算式如下

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 就是這個了 , 雖然這個Regex有點長,但用它可以把驗證和分割一步到位,後面轉換的時候就省掉了分割IP地址的步驟;

方案1:每8位轉成16進位字元,拼接後轉成整數

當IP地址通過用“.”分割後,每一段都因該是8位,所以我們剛好可以轉成兩位的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地址的結構,不難想到只要給分割之後的數字乘以相應的數,再加起來就OK了;

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的值大於0x7fffffff(127.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"相差無幾,難道是因為V8? 

附上一個反函數:

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,謝謝!

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.