erlang中通过ip和子网掩码,计算地址范围 【二进制和十进制的转换】

      在程序中,难免用的二进制和十进制之间的转换。遇到一个场景,通过ip和子网掩码,计算地址范围。

而地址范围为:网络地址+1—— 广播地址 -1 .  网络地址即ip和子网掩码的与的位运算。广播地址为:网络地址的主机位全部换成1。

打个比方:

IP为: 192.168.0.0 /16 ,这里,/16表示前16为是网络位,后16位是主机位。

子网掩码为:255.255.255.0/24,这里,/24表示前24位是网络位,后8位是主机位。

要求得:地址范围,首先就需求出网络地址和广播地址。进而涉及到二进制和十进制之间的转换。

十进制转二进制,erlang有BIF内置函数,integer_to_list(X,Y),

举个栗子:在erlang的shell下,

         > erlang:integer_to_list(255,2), 

       > 11111111

出来的二进制为8个1。当然,还有函数实现的。

而二进制转换为十进制中, 在erlang的shell下,

>2#11111111,输出结果为255.

erlang没有直接调用二进制转换十进制的函数接口。于是,自己封装一个,如下:

% 2进制转换10进制 
testbin(X) ->
          A = integer_to_list(X div 10),
          B = X rem 10,
      erlang:trunc(bin2de(A)) + B.

bin2de([]) -> 0;
bin2de(A) -> 
         {L1,L2}  = lists:split(1,A),
         case list_to_integer(L1) of
                 1 -> math:pow(2,length(A)) + bin2de(L2);
                 0 -> bin2de(L2)
         end.

  思路很简单,就是除以10,取商和余数,分别做2的阶乘,最后再相加即可.

测试结果如图:

用2#数值,在shell下验证,结果一样的.

附代码如下:

-module(ip).

-compile(export_all).


test() ->
		%% 读配置文件
		%	{} = file:consult(),
		[A,B,C,D] = [192,4,0,1],
		[A1,B1,C1,D1] = [255,255,255,0],
			%%计算网络地址
			IP1  = [A,B,C,D], 
			IP2  = [A1,B1,C1,D1],
			NetAddress =  [A band A1, B band B1, C band C1, D band D1],
			io:format("NetAddress.....~p~n",[NetAddress]),					%%网络地址的十进制
			% Netaddressbin = lists:map(fun(X) ->  de2bin(X,[]) end, NetAddress),
			% io:format("Naddressbin.....~p~n",[Netaddressbin]),				%%网络地址的二进制

%%网络地址的二进制
			Netaddressbin1 = lists:map(fun(X) ->  
			                                     case length(integer_to_list(X,2))  of
			                                     		8 -> integer_to_list(X,2);
			                                     		7 -> "0" ++ integer_to_list(X,2);
			                                     		6 -> "00" ++ integer_to_list(X,2);
			                                     		5 -> "000" ++ integer_to_list(X,2);
			                                     		4 -> "0000" ++ integer_to_list(X,2);
			                                     		3 -> "00000" ++ integer_to_list(X,2);
			                                     		2-> "000000" ++ integer_to_list(X,2);
			                                     		1 -> "0000000" ++ integer_to_list(X,2)
			                                     	end
			                                      end, NetAddress),
			io:format("Naddressbin1.....~p~n",[Netaddressbin1]),				

			% 计算广播地址(广播地址是网络地址的主机位全部换成1后, 在减去1)
			% BroadcastAddress = 
			IP1bin = lists:map(fun(X) -> integer_to_list(X,2)  end, IP1),
			io:format("IP1bin.....~p~n",[IP1bin]),

			IP2bin = lists:map(fun(X) -> integer_to_list(X,2)  end, IP2),
			io:format("IP2bin.....~p~n",[IP2bin]).


% 2进制转换10进制 
testbin(X) ->
		  A = integer_to_list(X div 10),
		  B = X rem 10,
		  erlang:trunc(bin2de(A)) + B.

bin2de([]) -> 0;
bin2de(A) -> 
		 {L1,L2}  = lists:split(1,A),
		 case list_to_integer(L1) of
		 		1 -> math:pow(2,length(A)) + bin2de(L2);
		 		0 -> bin2de(L2)
		 end.


% 10进制转换2进制
de2bin(0,Acc) ->   Acc;
de2bin(N,Acc) ->   
	de2bin(N bsr 1,[((N band 1)+$0)|Acc]).


tempData([0])-> [];  
tempData([Num]) ->
    Result = Num band 1,     
    integer_to_list(Result) ++ tempData([Num bsr 1]).  
 
de2Binary(Num)->  
    BinaryList = lists:reverse(tempData([Num])),
    LoopTimes = length(BinaryList) rem 8,
    if LoopTimes > 0 -> addBlank(BinaryList,8 - LoopTimes);
       true -> BinaryList
    end.
 
addBlank(BinaryList,0) -> BinaryList;
addBlank(BinaryList,Times) ->
    addBlank("0" ++ BinaryList,Times-1).

  

原文地址:https://www.cnblogs.com/unqiang/p/8317061.html