学校学的都还给老师了,╮(╯▽╰)╭哎
原码、反码、补码
首先计算机里面保存的数据都是由二进制组成0、1,既然有数据就有正负之分。
原码就是这些二进制的组合,首位为符号位,0表示正数,1表示负数。
例如1的4位二进制就是0001,-1的4位二进制就是1001
原码通俗点说就是给人看的,但是计算机需要对二进制进行运算啊,例如1+(-1)应该等于0,
如果用原码进行求和就是0001+1001=1010 变成了十进制的(-2),结果不对啊,为了解决这个问题就引导出
了反码的概念,反码是用来处理负数的,
正数的反码就是本身,负数反码就是符号位置不变,其他位置变反过。
还是刚刚的例子,1+(-1)=0001+1110=1111 反码1111的原码等于(1000)等于十进制的(-0),按道理
0不应该有正负之分,为了解决这个问题,引入了补码的概念,同样,补码是用来处理负数的,
正数的补码就是其本身,负数的补码就是在反码的基础上+1。(负数的补码是在原码的基础上除符号位外其余位取反后+1)
原码 反码 补码
0001+(1001)=》0001+1110=》0001+1111(1110+1)=10000,去掉最高位就是0000,解决了-0的问题。
由此推导出计算机在运算中用的都会补码方式进行计算。
在Java中,所有数据的表示方法都是以补码的形式表示
补码与原码关系:
正数补码与原码相同,负数补码是原码减1后取反。
%运算
通过取模操作可以获取某个数之间的随机数,例如 a%10 可以获取到0~9之间随机值
&运算
与运算 如果相对应位都是1,则结果为1, 否则为0 规则 :都为1时才为1
|运算
如果相对应位都是0,则结果为0,否则为1,有一个为1,则为1
~运算
按位取反运算符翻转操作数的每一位,即0变成1,1变成0。
非运算是根据补码来计算的
例如 5的非运算
~5= -6
// 5的原码0101 取反就是 1010
// 1010 求反码 1101 求补码 1110
20180920-Java位运算的使用场景
1、乘法 a * (2^n) 等价于 a << n
3*2=3<<1
3*4=3<<2
2、除法 a / (2^n) 等价于 a>> n
8/2=8>>1
8/4=8>>2
3、取模运算,采用位运算实现 a % (2^n) 等价于 a & (2^n - 1)
9%4=9&3
首先位移运算肯定是高效的,jdk源码有大量使用
(1)机器都是使用补码,运算也是使用补码运算。
(2)正数的原码补码反码都一样。
(2)补码与原码相互转换,其运算过程是相同。
带符号左位移运算符<< ,数值的补码全部往左移动X位: a<<1 等于a*2 ,左移n位就相当于乘以2的n次方
例如1<<1 等于0001向左边位移一位,00010
带符号右位移运算符>> a>>1 等于a/2 ,右移n位就相当于除以2的n次方
&与运算,就是按位与运算,两个1才是1,否则都是0
例如2&1 等于0010和0001 与运算,结果就是0000。
一般常用的就是某个数a&1,那么结果要么是0要么是1。
掩码使用例子
例如权限控制,例如增删改查四个权限控制
如果是组合权限那么会有16种情况
这时候我们就可以用二进制来实现
1<<0 0001 增
1<<1 0010 删
1<<2 0100 改
1<<3 1000 查
假设flag=0
添加增权限就是 :
flag=(flag|0001)=0001
删除 增的这个权限(0001)就是:
flag&=~0001
1、 ~0001=1000(去反数)
2、0001&(1000)=0000 (再和原来的数取与)
判断限就是
& 是两个都是1 才会大于0
flag&0010=(0001&0001)>0
public static class RoleCodeMask {
//教师0001
public static final int teacherRoleCode = 1 << 0;
//校长0010
public static final int principalRoleCode = 1 << 1;
//教导0100
public static final int subjectLeaderRoleCode = 1 << 2;
//当前状态
private int currentStatus;
public void add(int code) {
currentStatus = currentStatus | code;
}
public boolean contains(int code) {
return (currentStatus & code) > 0;
}
// 当前权限是 0111 教师、校长、教导
// 删除教师权限0001,则 0111 &
public void delete(int more){
// 如果非操作不好理解,可以理解为 减(-)操作也是可以的
// currentStatus = currentStatus - more;
currentStatus &= ~more;
}
}
进制之间转化
核心思路是求余数求商
例如10进制转2进制
int i=110112;
String two="";
while (i>0){
two=i%2+two;
i=i/2;
}
编译与解释
java文件->编译->.class文件,编译成.class字节码,.class需要jvm解释,然后解释执行
。Java很特殊,Java程序需要编译但是没有直接编译成机器语言,即二进制语言,而是编译成字节码(.class)再用解释方式
执行。java程序编译以后的class属于中间代码,并不是可执行程序exe,不是二进制文件,
所以在执行的时候需要一个中介来解释中间代码,这既是java解释器,也就是所谓的java虚拟机(JVM),也叫JDK。