简介:
ip地址实际上是一个32位的二进制数,不过为了表示方便,我们通常以每八位的十进制,中间用点隔开,便于记忆。
例如10.10.1.1 →00001010,000010101,00000001,00000001
要想把点分制的ip地址转化为十进制,首先要了解一下2进制和十进制的相互转化。
二进制转十进制:
从低位开始,连续(当前位)*(2n)相加,n从0累加。
例如100,就是0*1+0*2+0*4=4.
十进制转二进制:
连续除2,从得数到余数,依次倒序排列。
例如9/2→4余1,4/2→2余0,2/2→得1余0,得数为1,余数为,001,从得数拼起来就是1001
转化:
在某些情况下,我们需要用到ip地址的int型,而不是一串便于阅读的字符串。
这里要先说一下思路:
例如10.10.1.1,你可以先把它转化成二进制00001010,000010101,00000001,00000001,然后再用上面的二进制转10进制的方法来
但是如果先把ip先转成二进制再转成十进制就太麻烦了,稍微观察一下我们就会发现,点分制的ip地址相比正常的二进制转成十进制,只不过是每八位都少乘了一个28*n而已(n从0开始)
那么这个计算就很简单了,10.10.1.1的十进制就是10*28*3+10*28*2+1*28*1+1*28*0=168427777
ip地址转化为十进制1(乘法):
private int ipTo10Int(String ip) { int ret = 0; if (ip != null) { String[] array = ip.split("\.");//split的参数是正则表达式,不可直接填".",否则split结果为[]
//注意,提取出来的数组是{“10”,“10”,“1”,“1”},数组的第一位是10,并不是1,不要把1当做低位 int length = array.length; for (int i = 0; i < length; i++) { int num = Integer.valueOf(array[i]); ret += (int) num * Math.pow(2, (length - 1-i) * 8); } } return ret; }
其实上面的运算有一个风险,java的int是32位,其中1位为符号位,只有31位可以表示数据,最大数值为231-1,这个值其实远远不够来表示ip地址。
例如,某个掩码地址为255.255.255.255,光是高位255的运算结果(28-1)*224>231-1就已经超出int的表示范围了。不过一般ip地址的运算是不会超过这个范围的。
如果对位移比较熟悉的话,也可以用位移来实现:
ip地址转化为十进制2(位移):
private int ipTo10Int2(String ip) { int ret = 0; if (ip != null) { String[] array = ip.split("\."); int length = array.length; for (int i = 0; i < length; i++) { int num = Integer.parseInt(array[i]); ret |= num << (8 * (length - 1 - i));//每八位左移3-i位就相当于乘以23-i了,然后用|运算相加,结果是一样的 } } return ret; }
反过来,如果有一个int类型的ip地址,也可以转化为点分制的ip地址,如果人工计算,思路是先转化成二进制再按八位划分成十进制,但是对电脑而言,位移就可以了
这就是机器运算的快捷之处,不管你用的是几进制,对计算机而言,都是二进制,直接&或者|,就能得到想要的结果
十进制ip地址转化为点分制(位移):
private String intToIp(int ip) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 4; i++) { sb.append((ip >> (3 - i) * 8) & 0xff); if (i < 3) { sb.append("."); } } return sb.toString(); }