二进制与进制转换


二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”,由18世纪德国数理哲学大师莱布尼兹发现。当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的。计算机中的二进制则是一个非常微小的开关,用“开”来表示1,“关”来表示0。




二进制的转换:


例如,设有一个二进制数:0110 0100(由后至前分别为第0位,第1位……第7位),转换为10进制为:

下面是竖式:

01100 100 换算成 十进制

第0位 0 x 2^0 = 0

第1位 0 x 2^1 = 0

第2位 1 x 2^2 = 4

第3位 0 x 2^3 = 0

第4位 0 x 2^4 = 0

第5位 1 x 2^5 = 32

第6位 1 x 2^6 = 64

第7位 0 x 2^7 = 0




(01100 100) =100




二进制位运算


优点:特定情况下,计算方便,速度快;由于多数电子设备都由二进制书写的,所以支持面广;较于算术方法,逻辑简单。(机器默认32位)




按位与(&)


两位全为1,结果才为1: 0&0=0;  0&1=0;   1&0=0;    1&1=1;


例如:51&5  即0011 0011 & 0000 0101 = 0000 0001 所以51&5=1.


用法:


(1)清零:如果想要一个单位清零,那么使其全部二进制为0,只要与一个各位都为零的数值想与,结果为零。




(2)取一个数中指定位:找一个数,对应X要取的位,该数的对应位为1,其余位为零,此数与X进行“与运算”可以得到X中的指定位。


例如:设X=1010 1110,取X的低4位,用X & 0000 1111 = 0000 1110 就可以得到



按位或(|)


只要有一个为1,结果就为1: 0|0=0;   0|1=1;   1|0=1;   1|1=1;


例如:51|5 即00110011 | 0000 0101 = 0011 0111 所以51|5 =55;


用法:常用来对一个数据的某些位置1;找到一个数,对应X要置1的位,该数的对应位为1,其余位为零。此数与X相或可使X中的某些位置1。


例如:将X=1010 0000 的低四位置1,用X | 0000 1111 =1010 1111 就可以得到




异或运算(^)


两个相应位为“异”(值不同),则该位结果为1,否则为0:  


0^0=0;  0^1=1;  1^0=1; 1^1=0;


例如:51^5 即 0011 0011 ^ 0000 0101 = 0011 0110 所以51^5=54;


用法:


(1)使特定位翻转:找一个数,对应X要翻转的各位,该数的对应位为1,其余位为零,此数与X对应位异或就可以得到;


例如:X=1010 1110,使X低4位翻转,用X ^ 0000 1111 = 1010 0001就可以得到




(2)与0相异或,保留原值


例如:X ^ 0000 0000 = 1010 1110 




(3)两个变量交换值的方法:


1、借助第三个变量来实现: C=A; A=B; B=C;

2、 利用加减法实现两个变量的交换:A=A+B; B=A-B;A=A-B;

3、用位异或运算来实现:利用一个数异或本身等于0和异或运算符合交换律

例如:A=A^B;B=A^B;A=A^B;




取反运算(~)


对于一个二进制数按位取反,即将0变1,1变0: ~1=0;  ~0=1;




左移运算(<<)


将一个运算对象的各二进制位全部左移若干位(左边的二进制丢弃,右边补零)


2<<1 = 4 :  10 <<1 =100=4


若左移时舍弃的高位不包括1,则每左移一位,相当于该数乘以2。


例如:


11(1011) << 2 = 44  
11(0000 0000 0000 0000 0000 0000 1011)(32bit)   (在JAVA中整型是32位的,前面的0都省略了,所以1011中第一个“1”并不是高位,实际上是符合高位不包括1的条件)


-14(二进制:1111 0010)<< 2= (1100 1000)  (高位包括1,不符合规则)




右移运算(>>)


将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。操作数每右移一位,相当于该数除以2.




左补0 or 补1 得看被移数是正还是负。


例:1=4 >> 2


例:-14(1111 0010) >> 2 = -4 (1111  1100 )



无符号右移运算(>>>)


各个位向右移指定的位数。右移后左边突出的位用零来填充。移出右边的位被丢弃


例如:   -14>>>2   


10)>>> 2


0011 1111 1111 1111 1111 1111 1111 1100)


           =  1073741820




负数以其正值的补码形式表示


原码: 一个整数按照绝对值大小转化成的二进制数为原码


           例如:14的原码为0000 0000 0000 0000 0000 0000 0000 1110




反码:将二进制数按位取反,所得的新二进制数称为原二进制数的反码。


           例如:14的反码为1111 1111 1111 1111 1111 1111 1111 0001




补码:反码加1称为补码


0001 +1 = 1111 1111 1111 1111 1111 1111 11110010






                  -14(1111 1111 1111 1111 1111 1111 1111 0010)<< 2


00)


                   =?  (即为-56)


  分析:


          只需要求出该补码的原码对应的正值,然后取相反数:


           1、补码减一得到反码:(...1100 0111)


           2、补码取反得到原码(即该负数的正值) (...0011 1000)


           3、计算正值  按照二-十进制转换规则,正值为56


           4、取相反数就会得到负数:-56



------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


JDK内置的进制转换


Java内置的进制转换:




         十进制转成十六进制         

             Integer.toHexString(int i)     

           十进制转成八进制         

            Integer.toOctalString(int i)     

           十进制转成二进制         

           Integer.toBinaryString(int i)     

         十六进制转成十进制         

    Integer.valueOf("FFFF",16).toString()     

           八进制转成十进制         

       Integer.valueOf("376",8).toString()     

           二进制转成十进制         

      Integer.valueOf("0101",2).toString()     



示例代码:


public static void main(String[] args) {
		//十进制转换成其他进制
		System.out.println("十进制转换成二进制:"+Integer.toBinaryString(112));
		System.out.println("十进制转换成十六进制:"+Integer.toHexString(112));
		System.out.println("十进制转换成八进制:"+Integer.toOctalString(112));
		
	    System.out.println("");  
		
		//其他进制转换成十进制
		System.out.println("二进制转换成十进制:"+Integer.parseInt("111001", 2));
		System.out.println("八进制转换成十进制:"+Integer.parseInt("27", 8));
		System.out.println("十六进制转换成十进制:"+Integer.parseInt("A8", 16));
		
		System.out.println(""); 
	        
	    System.out.println("二进制转换成十进制:"+Integer.valueOf("111001",2).toString());
		System.out.println("八进制转换成十进制:"+Integer.valueOf("27",8).toString());
		System.out.println("十六进制转换成十进制:"+Integer.valueOf("A8",16).toString());
	}





Java中的进制


Java平时开发中“进制转换”和“位操作”用的不多,Java处理的是高层;


在跨平台中用的较多,如:文件读写,数据通信.




Java中基本类型:




int数据类型:byte(8bit ,-128~127)        short(16 bit)       int(32 bit)   long(64 bit)




float数据类型: 单精度(32 bit  float)、双精度(64 bit  double)




boolean类型:  true  false 




char数据类型:unicode字符(16位) 




对应的类类型:




Integer、Float、Boolean、Character、Double、Short、Byte、Long






数据类型转化成字节:




8143(0000 0000 0000 0000 0001 1111 1100 1111)  => byte[] b =[-49,31,0,0]


第一个(低端)字节:8143>>0*8 & 0xff =(1100 1111)= 207(或有符号的-49)


第二个(低端)字节:8143>>1*8 & 0xff =(0001 1111)= 31


第三个(低端)字节:8143>>2*8 & 0xff =(0000 0000)= 0


第三个(低端)字节:8143>>2*8 & 0xff =(0000 0000)= 0





PS:


小端法(Little-Endian):低位字节排放在内存的低地址端即该值的起始地址,高位字节排放在内存的高地址端


大端发(Big-Endian):高位字节排放在内存的低地址端即该值的起始地址,低位字节排放在内存的高地址端




例如:


32bit宽的数0x12 34 56 78 


在Little-endian模式CPU内存中存放的存放方式(假设从地址0x4000开始存放)为:




而在Big-endian模式CPU内存中的存放方式则为:






字符串->字节数组


String s;  byte[] bs =s.getBytes();




字节数组->字符串


byte[] bs = new byte[int];


String s = new String(bs);或


String s = new String(bs,encode); //encode指编码方式“gb2312,utf-8”