二进制与进制转换
二进制是计算技术中广泛采用的一种数制。二进制数据是用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”