zoukankan      html  css  js  c++  java
  • javascript把IP地址转为数值几种方案,来挑战一下效率吧

    为什么要转化IP地址:

    点分十进制表示法只是为了让人好记忆,并不能用于电脑运算;

    数据库中跟IP地址有的字段一般都会存成整数,这样便于查询,也可以提高了查询速度;

    javascript中转换的几种方案:

    首先说一下IP地址的验证,

    这里就用正则表达式验证的方式,表达式如下

    var REG =/^(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5])$/;

    后面代码中用到 REG 就是这个了 , 虽然这个正则表达式有点长,但用它可以把验证和分割一步到位,后面转换的时候就省掉了分割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,谢谢!

  • 相关阅读:
    ubuntu下进程kidle_inject致使编译软件很慢
    linux下保存下位机输出的串口信息为文件
    ubuntu下转换flv格式为mp4格式
    ubuntu下安装mkfs.jffs工具
    linux下安装evernote国际版
    linux 下使用命令查看jvm信息
    linux下面实时查看进程,内存以及cpu使用情况使用命令
    Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析
    linux如何复制文件夹和移动文件夹
    linux解压war包的命令
  • 原文地址:https://www.cnblogs.com/whyoop/p/3140803.html
Copyright © 2011-2022 走看看