进制转换
首先我们先来了解下进制间是如何转换的。
常用进制
- 二进制 : 0-1 逢二进一
- 八进制 0-7 逢八进一
- 十进制 0-9 逢十进一
- 十六进制 0-9 A-F表示10-15 逢十六进一
eg:二进制转10进制
所有向十进制转换的都可以采用这样的方式进行计算,二进制以二为底 8进制以8为底,16进制以16为底
十进制转二进制
二进制的加减乘除
- 加法:
- 减法:
乘法:
除法:
乘法除法暂未研究,后续会进行补充
了解了这么多我们开始java的位运算吧。
JAVA位运算
java中,位运算包括 ^(亦或), &(与),|(或) ,<<(左移),>>(右移),<<<(无符号左移),>>>(无符号右移)在继续往下看之前,我们还要了解什么是机器码,由于计算机只能识别0和1, 所有在计算机中用0和1表示正负,这就是符号位(最高位表示),符号位连同数据一起代码化的就是机器码。机器码加绝对值表示的数值就是真值。机器码分有符号数和无符号数,无符号数由所有数值表示。
计算机系统中,数值一律用补码来表示:因为补码可以使符号位和数值位统一处理,同时可以使*减法按照加法来处理。数值编码分为原码,反码,补码,符号位(最高位)均为0正1负。*
原码表示最接近真值 ,规定最高位为符号位 0+ 1- 数值在符号位后面以绝对值给出
补码表示就是将符号位作为数值参与运算,并使所有加减以均以加法代替。负数的补码是原码取反加一,正数补码是它本身。
反码是一种特殊的补码,反码的模比补码最低位小1
- 原码 -> 补码: 数值位取反加1.
- 补码 -> 原码: 对该补码的数值位 取反 加1.
- 补码 的绝对值(称为真值):正数的真值就是本身,负数的真值是各位(包括符号位)取反加1(即变成原码并把符号位取反).
NOTE* 补码”或”运算之后为补码
^(亦或)
public static void main(String[] args) {
int a=-14;// 0000 1110
int b=-9;// 0000 1001
/*相同为0,不同为1 */
/* 符号位(0) | 符号位(1) 14 取反 加一
* 0000 1110 14 | 1111 0010 -14 补码 0000 1110->1111 0001->1111 0010
* ^ 0000 1001 9 | ^ 1111 0111 -9 补码 0000 1001->1111 0110->1111 0111
* --------------- | ----------------- 补码"异或"运算之后为补码
* 0000 0111 补码->源码 0000 0111 | 0000 0101 补码->源码 0000 0101
* 1*2^2+1*2^1+1*2^0=7 | 1*2^2+1*2^0 =5 结果 5
* */
System.out.println("a与b:"+String.valueOf(a^b));
}
&(与)
public static void main(String[] args) {
int a=-1;//0000 0001 ->1111 1110->1111 1111 负数 补符号位(符号位不变)1 取反加一
int b=10;//0000 1010 符号位0
/*同1为1,否则为0*/
/* |
* 1111 1111 -1 | 1111 0010 -14 补码 0000 1110->1111 0001->1111 0010
* & 0000 1010 10 | & 1111 0111 -9 补码 0000 1001->1111 0110->1111 0111
* -------------- | ----------------
* 0000 1010 ->0000 1010 | 1111 0010 -> 1000 1101->1000 1110
* 1*2^3+1*2^1=10 | 1*2^3 +1*2^2+1*2^1= -14
* 最高为是0,不用转化 如果最高位为1 即负数 最高位不变 其他位取反,加一
*
* */
System.out.println("a与b:"+String.valueOf(a&b));
}
|(或)
public static void main(String[] args) {
int a=14;// 0000 1110
int b=9;// 0000 1001
/*有1为1,否则为0 */
/* 符号位(0) | 符号位(1) 负数最高位为1 其他位取反加一
* 0000 1110 14 | 1111 0010 -14 补码0000 1110->1111 0001->1111 0010
* | 0000 1001 9 | | 0000 1001 9 补码
* --------------- | -----------------
* 0000 1111 -> 0000 1111 | 1111 1011 ->1000 0100 -> 1000 0101
* | 补码转原码取反加一
* 1*2^3+1*2^2+1*2^1+1*2^0=15 | 1*2^2+1*2^0 =5 符号位为负 结果-5
* */
System.out.println("a与b:"+String.valueOf(a|b));
}
<<(左移)
左移位运算符为«,其运算规则是:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。
public static void main(String[] args) {
int a=-14;// 0000 1110
int b=11; // 0000 1011
/* |符号位(1)取反 | 加一
* 0000 1110 ->| 1111 0001 -> | 1111 0010
* << 左移1 (1)舍去 1110 0100 左移后的补码 正数最高位补0,负数最高位补1
* 1001 1011 符号位不变 取反
* 1001 1100
* - 1*2^2+1*2^3+1*2^4= 4+8+16=28
* 符号位为负 结果负28
*---------------------------------------------------------------------
* 0 000 1011
* << 左移1 0 000 1011 0 正数补0 正数的补码和原码相同
* + 1*2^4+1*2^2+1*2^1= 22
*
* */
System.out.println("a与b:"+String.valueOf(a<<1));
System.out.println("a与b:"+String.valueOf(b<<1));
}
>>(右移)
右位移运算符为»,其运算规则是:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补零。
public static void main(String[] args) {
int a=-14;// 0000 1110
int b=11; // 0000 1011
/* |符号位(1)取反 | 加一
* 0000 1110 ->| 1111 0001 -> | 1111 0010
* >> 右移3 111 1111 0(010)舍去 左移后的补码 正数最高位补0,负数最高位补1
* 100 0000 1 符号位不变 取反
* 100 0001 0 +1
* - 1*2^1=2
* 符号位为负 结果负2
* 右移与左移不同会把移出去的舍掉
*---------------------------------------------------------------------
* 0 000 1011
* >> 右移3 0 000 0001(011) 正数补0 正数的补码和原码相同
* + 1*2^0= 1
*
* */
System.out.println("a与b:"+String.valueOf(a>>3));
System.out.println("a与b:"+String.valueOf(b>>3));
}
~(取反)
取反就是1为0,0为1
public static void main(String[] args) {
int a=~-14;// 0000 1110
int b=~11; // 0000 1011
/*
* 0000 1110 -->1111 0001-->1111 0010
* 取反后 ---> 0 000 1101 13
*----------------------------------------------------------------
* 0000 1011
* 取反后 ---> 1 111 0100 (最高位为1)负数 负数都是补码表示,所有要转换为原码
* 转换后 ---> 1 000 1100 --> -12
*
* */
System.out.println("a与b:"+String.valueOf(a));
System.out.println("a与b:"+String.valueOf(b));
}
>>>(无符号右移)
public static void main(String[] args) {
int a = -14;// 0000 1110->1111 0010
int b=11; // 0000 1011
/*
*无符号右移中正数和负数计算方式不同,对于正数,不会改变成负数,对于负数,将会变成正数。
* --------------------------------------------------
* 负数无符号右移
* 11111111111111111111111111110010
* 00011111111111111111111111111110(010)舍去
* 536870910
* --------------------------------------------------
* 正数无符号右移
* 00000000000000000000000000001011
* 00000000000000000000000000001(011)舍去
* 1
* */
System.out.println("a无符号右移3:"+String.valueOf(a>>>3));
System.out.println("b无符号右移3:"+String.valueOf(b>>>3));
}
*NOTE: 遇到&= 、|= 、 ^= 、>>= 、>>>=、 <<= 这样的他们表示把计算后的变量重新赋值给变量,就和a+=1 表示 a=a+1 一样。
*NOTE: 为何无符号位移时有32位呢,请看下表
数据结构 | 字节 | 范围 |
boolean | 1 | true或false |
char | 2 | 从字符型对应的整型数来划分,其表示范围是0~65535 |
byte | 1 | -128~127 |
short | 2 | -32768~32767 |
int | 4 | -2147483648~2147483647 (-2^31 ~ 2^31-1) |
long | 8 | -9223372036854775808 ~ 9223372036854775807 |
float | 4 | -3.4E38~3.4E38 |
double | 8 | -1.7E308~1.7E308 |