左移
- m<<n:把整数m表示的二进制数左移n位,高位移出n位都舍弃,低位补0
- m<<n即在数字没有溢出的前提下,对于正数和负数,左移n位都相当于m乘以2的n次方
- 运算方式:数值的补码全部往左移动X位,符号位和最高位都舍弃,最低位补0
负数:
int a = -5 ;
int b = a << 2 ;
[ 1000 0000 0000 0000 0000 0000 0000 0101 ] -5的原码
[ 1111 1111 1111 1111 1111 1111 1111 1010 ] -5的反码
[ 1111 1111 1111 1111 1111 1111 1111 1011 ] -5的补码
[ 1111 1111 1111 1111 1111 1111 1110 1100 ] a<<2左移2位
将补码转换成原码就可以得到数值,补码转原码和原码转补码一样。
[ 1000 0000 0000 0000 0000 0000 0001 0011 ]
[ 1000 0000 0000 0000 0000 0000 0001 0100 ] 得到a<<2的原码,即 -20
左移n位就相当于乘以2的n次方
右移
- m>>n的含义:把整数m表示的二进制数右移n位,m为正数,高位全部补0;m为负数,高位全部补1
- m>>n即m除以2的n次方,得到的为整数时,即为结果。如果结果为小数,此时会出现两种情况: 如果m为正数,得到的商会无条件 的舍弃小数位; 如果m为负数,舍弃小数部分,然后把整数部分加+1得到位移后的值
- 运算方式:数值的补码向右移X位,符号位不变(左边补上符号位)
负数:
int a = -8 ;
int b = a >> 1 ;
[ 1000 0000 0000 0000 0000 0000 0000 1000 ] -8的原码
[ 1111 1111 1111 1111 1111 1111 1111 0111 ] -8的反码
[ 1111 1111 1111 1111 1111 1111 1111 1000 ] -8的补码
[ 1111 1111 1111 1111 1111 1111 1111 1100 ] a>>1向右移1位
补码转原码
[ 1000 0000 0000 0000 0000 0000 0000 0011 ]
[ 1000 0000 0000 0000 0000 0000 0000 0100 ] 得到a>>1的原码,即 -4
/**
将一个int数字转换为二进制的字符串形式。`
* @param num 需要转换的int类型数据`
* @param digits 要转换的二进制位数,位数不足则在前面补0`
* @return 二进制的字符串形式`
*/
public static String toBinary(int num, int digits) {
String cover = Integer.toBinaryString(1 << digits).substring(1);
String s = Integer.toBinaryString(num);
return` `s.length() < digits ? cover.substring(s.length()) + s : s;
}
示例
public class Test {
public static void main(String[] args) {
byte[] a = new byte[10];
a[0]= -127;
System.out.println(a[0]);
int c = a[0]&0xff;
System.out.println(c);
}
}
结果:
-127
129
- 当将-127赋值给a[0]时候,a[0]作为一个byte类型,计算机存储的补码是10000001(8位)。
- 将a[0] 作为int类型向控制台输出的时候,jvm作了一个补位的处理,因为int类型是32位所以补位后的补码就是1111111111111111111111111 10000001(32位),这个32位二进制补码表示的也是-127.
- 为什么byte类型的数字要&0xff再赋值给int类型?
其本质原因就是想保持二进制补码的一致性,当byte要转化为int的时候,高的24位必然会补1,其二进制补码其实已经不一致,&0xff可以将高的24位置为0,低8位保持原样。这样做的目的就是为了保证二进制数据的一致性,保证了二进制数据性的同时,如果二进制被当作byte和int来解读,其10进制的值必然是不同的,因为符号位位置已经发生了变化.
int c = a[0]&0xff;
a[0]&0xff=111111111111111111111111110000001&11111111=000000000000000000000000 10000001
- 这个值算一下就是129,为什么上面的式子中a[0]不是8位而是32位,因为当系统检测到byte可能会转化成int或者说byte与int类型进行运算的时候,就会将byte的内存空间高位补1(也就是按符号位补位)扩充到32位,再参与运算。0xff其实是int类型的字面量值
/**
* int转byte[]
* 该方法将一个int类型的数据转换为byte[]形式,因为int为32bit,而byte为8bit所以在进行类型转换时,知会获取低8位,
* 丢弃高24位。通过位移的方式,将32bit的数据转换成4个8bit的数据。注意 &0xff,在这当中,&0xff简单理解为一把剪刀,
* 将想要获取的8位数据截取出来。
* @param i 一个int数字
* @return byte[]
*/
public static byte[] int2ByteArray(int i){
byte[] result=new byte[4];
result[0]=(byte)((i >> 24)& 0xFF);
result[1]=(byte)((i >> 16)& 0xFF);
result[2]=(byte)((i >> 8)& 0xFF);
result[3]=(byte)(i & 0xFF);
return result;
}
/**
* byte[]转int
* 利用int2ByteArray方法,将一个int转为byte[],但在解析时,需要将数据还原。同样使用移位的方式,将适当的位数进行还原,
* 0xFF为16进制的数据,所以在其后每加上一位,就相当于二进制加上4位。同时,使用|=号拼接数据,将其还原成最终的int数据
* @param bytes byte类型数组
* @return int数字
*/
public static int bytes2Int(byte[] bytes){
int num=bytes[3] & 0xFF;
num |=((bytes[2] <<8)& 0xFF00);
num |=((bytes[1] <<16)& 0xFF0000);
num |=((bytes[0] <<24)& 0xFF0000);
return num;
}