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)。javascript
點分十進制表示法只是爲了讓人好記憶,並不能用於電腦運算;java
數據庫中跟IP地址有的字段通常都會存成整數,這樣便於查詢,也能夠提升了查詢速度;git
首先說一下IP地址的驗證,github
這裏就用正則表達式驗證的方式,表達式以下正則表達式
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 就是這個了 , 雖然這個正則表達式有點長,但用它能夠把驗證和分割一步到位,後面轉換的時候就省掉了分割IP地址的步驟;數據庫
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); }
若是不要驗證的話就能夠換一個帥氣一點的寫法:markdown
function ipToInt(IP){ return parseInt(IP.replace(/\d+\.?/ig,function(a){ a = parseInt(a); return (a > 15 ? "" : "0") + a.toString(16); }),16); }
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])); }
直接記算還不如按位運算,那不是更快?函數
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進制的課哦。oop
上面按位運算看起來沒什麼問題,
試了幾個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位,剛恰好,否則這個方案只能放棄了。
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,謝謝!