关于二进制
一. 概念
电子计算机处理的信息,都是仅用“0”与“1”两个简单数字表示的信息,或者是用这种数字进行了编码的信
息。这种数制叫做二进制。现在在使用的计算机基本上都是二进制进行运算的。那么二进制有什么好处了?
(1)技术实现简单,计算机是由逻辑电路组成,逻辑电路通常只有两个状态,开关的接通与断开,这两种状态正好可以用“1”和“0”表示。
(2)简化运算规则:两个二进制数和、积运算组合各有三种,运算规则简单,有利于简化计算机内部结构,提高运算速度。
(3)适合逻辑运算:逻辑代数是逻辑运算的理论依据,二进制只有两个数码,正好与逻辑代数中的“真”和“假”相吻合。
(4)用二进制表示数据具有抗干扰能力强,可靠性高等优点。因为每位数据只有高低两个状态,当受到一定程度的干扰时,仍能可靠地分辨出它是高还是低。
但是由于二进制的位数比较长,例如byte是一个字节的取值范围是-128到127,用二进制表示就8个bit位,而int
则占四个字节所以长度就是32bit位,从这来看如果用二进制在书写和阅读方面不太方便。所以大部分的编程语言都没有
直接表示二进制都使用10进制和16进制来进行表达的。那既然要了解二进制,那就要先看看二进制是如何存储的?
二 编码方式
二进制中进行存储的编码方式有三种 :原码,反码及补码,而通常情况下数据在计算机中主要是以补码的形式存储的。
1.原码
原码就是这个数的绝对值的二进制加上符号位(即它的第一位),正数的符号位代表 0,负数的符号位代表1。
例如 byte a =2 ;
十进制 = 二进制原码
2 = 0000 0010;
-2 = 1000 0010;
2.反码
如果整个数是正数则其反码就是其本身,如果这个数是负数其反码就是除了符号位外其余位取反 即0变1,1变0
例如:byte a =1;
十进制 二进制原码 二进制反码
1 0000 0001 0000 0001
-1 1000 0001 1111 1110
3.补码
如果这是个正数则其补码就是其原码, 如果是负数则就是其反码加1
例如:byte a =1;
十进制 二进制原码 二进制反码 二进制补码
1 0000 0001 0000 0001 0000 0001
-1 1000 0001 1111 1110 1111 1111
所以以上就是二进制的集中存储方式,正数都都是其本身,而负数则不一样,所以要计算负数的值就需要逆推得到
其原码进行计算。
三 2进制的计算
那了解了二进制的存储方式那接下来就来说下二进制如何进行计算的 ,因为二进制只有 0 和1 两位所以其计算也是
在这个基础上。这些计算都是以补码计算的。
1.二进制的加法
1+0 =1,1+1=10,0+0 =0,0+1=1
例子:
int a =1,b =2;
a +b = 3;
a +b = 0000 0001 + 0000 0010 = 0000 0011;
2.二进制的减法
例子:
1-1 =0,1-0=1,0-1 =1(向前接位)
int a =1,b =2;
a -b = -1;
a -b = 0000 0001 - 0000 0010 = 1111 1111 ;
3.二进制的乘法
1*0 =0,1*1=1,0*1=0,0*0=0;
例子:
int a =1,b =2;
a *b = 0001 * 0010 = 0001 1110
具体的算法就是前一个数的每一个乘后面的数所有位,然后按位相加
0 x0010=0000最高位:0000---(千位移三位)
0 x0010=0000次高位:-0000--(百位移两位)
0 x0010=0000次低位:--0000-(十位移一位)
1 x0010=0010最低位 : ---0010(个位不移位)
然后相加 =0000 0010
4.二进制的除法
0÷1=0,1÷1=1。
5.二进制的位与 |
0 | 1 = 1,0 | 0 =0,1 | 1=1,1 | 0 =1;
例子:
int a =1,b =2;
a | b = 0001 | 0010 = 0011 =3
6. 二进制的 &
0 & 1= 0,0 & 0 =0.1&1 =1,1&0=0
例子:
int a =1,b =2;
a & b = 0001 & 0010 = 0000 =0
7.二进制的 ^
0^ 1 =1,0^0 =0,1^0 =1,1^1=0.
例子:
int a =1,b =2;
a ^ b =0001 ^ 0010 = 0011 =3
- 二进制的~
就是取反 0变1,1变0.
例子:
int a =5 ;
a = 0101 = 1010 = -6;
9.二进制的>>
向右移动 n位 ,高位补符号位
如果是正数则高位补0.如果是负数高位补1
例子:
2>> 2
0010 —> 0000 = 0
-2 >> 2
1110 —> 1111 = -1
10. 二进制的 << ,向左移动n位,地位补0
例子:
2<< 2
0010—> 1000 = 8;
-2<<2
1110 —> 1111 1000 = -8
11.二进制的 >>> 无符号右移( >>> ) 高位补0
例子:
2>>>2
0010 —>0000 =0
四 关于二进制转换
1.转位16进制
从小数点开始,向左右二边按“四位一段”分段(不足补0),然后,每一段的四位二进制数就对应一位十六进制数。按照以下对应关系进行转换:
0000 —> 0
0001 —> 1
0010 —> 2
0011—> 3
0100 —> 4
0101 —> 5
0110 —> 6
0111 —> 7
1000 —> 8
1001 —> 9
1010 —> A
1011 —> B
1100 —> C
1101 —> D
1110 —> E
1111 —> F
例子:
0001 1111 专为16进制就是 1f,在java中 16进制通常标记为0x,所以上面就是0x1f
2.转10进制
二进制数据是采用位置计数法,其位权是以2为底的幂。从最低位(最右)算起,位上的数字乘以本位的权重,权
重就是2的第几位的位数减一次方。比如第2位就是2的(2-1次)方,就是2;第8位就是2的(8-1)次方是128。把
所有的值加起来。
例子:
0001 1111 = 16+8+4+2+1=31
10进制转二进制
整数除以2,商继续除以2,得到0为止,将余数逆序排列。
22 / 2 11 余0
11/2 5 余 1
5 /2 2 余 1
2 /2 1 余 0
1 /2 0 余 1
所以22的二进制是10110
小数乘以2,取整,小数部分继续乘以2,取整,得到小数部分0为止,将整数顺序排列。
0.8125x2=1.625 取整1,小数部分是0.625
0.625x2=1.25 取整1,小数部分是0.25
0.25x2=0.5 取整0,小数部分是0.5
0.5x2=1.0 取整1,小数部分是0,结束
所以0.8125的二进制是0.1101
十进制22.8125等于二进制10110.1101
附带:
二进制小数转10进制
1111.1011
整数部分 --》 1+2+4+8 =15
小数部分从最低位算起除以2加上前一位除以2以此往前算
.1011 —>((((1/2+1)/2)+0)/2+1)/2=0.6875
3.转8进制
二进制转换成八进制的方法是,取三合一法,即从二进制的小数点为分界点,向左(或向右)每三位取成一位
1=001
2=010
3=011
4=100
5=101
6=110
7=111
例子:
1111.1111 = 17.74
五 其它
最后还有一个就是当java中碰到 int 转byte ,活着byte 转 int的问题
例如
int a =129;
byte b = (byte)a;
像在这种情况下转换是会越界的,在java中一个byte 占一个字节,即8位比特;而int型占四个字节所以是32位。所以
当直接转换的时候就会抹去多余的位数,所以此时b不等于130 而是等于-127.a —> 专为二进制 0000 1000 0001 ,转
化为byte后前面的24位呗干掉了,所以位1000 0001,此时代表这个数为负数,而计算机中存储都是补码。所以此时b的
补码是1000 0001 ,逆推其反码为1000 0000,其原码就是 1111 1111即 -127,所以在Java中,当我们要将int 转换为
byte数组时,一个int就需要长度为4个字节的数组来存放,其中一次从数组下标为[0]开始存放int的高位到低位。代码如下
public static byte[] intToByte(int target) {
byte[] target = new byte[4];
//由高位到低位
target[0] = (byte)((i >> 24) & 0xFF); //转为byte后原来的前八位变为现在的现在的后八位
target[1] = (byte)((i >> 16) & 0xFF);//依次类推,分别将对应的位数转为byte中去
target[2] = (byte)((i >> 8) & 0xFF);
target[3] = (byte)(i & 0xFF);
System.out.println(Integer.toBinaryString(target[0]));
System.out.println(Integer.toBinaryString(target[1]));
System.out.println(Integer.toBinaryString(target[2]));
System.out.println(Integer.toBinaryString(target[3]));
return target;
}
public static int byteToInt(byte[] bytes) {
int value= 0;
//由高位到低位 ,将之前int的高位位置还原到之前的地方所以和之前的相反用<<
for (int i = 0; i < 4; i++) {
int position= (4 - 1 - i) * 8;
value +=(bytes[i] & 0xFF) << position;//往高位游
}
return value;
}
其它的转换都可以依次类推。 关于以上都是自己测试及查看相关资料整理的,如有什么问题欢迎指正。