原码、反码、补码
1什么是原码反码补码按照二进制进行存储运算:按照二进制补码方式参与运算原码:通过8421码快速计算数据大小(推荐使用计算器)直观的看数据的大小反码:在转换补码的过程中的中间值补码:参与运算2有符号数表示法怎么做有符号数:数据有正负之分就是有符号数,数据无正负之分就是无符号数例如:+7-7有符号数的组成:符号位+数值位例如inta=+7;所占字节数4b32位第一个0就是符号位0表示正数1表示负数00000000000000000000000000000111回顾:int表示范围2的32次方个数-2的31次方到+2的31次方-1//有一位是符号位所以31次方那么+7和-7在计算机中如何存储代码表示://inta=+7;inta=0b00000000000000000000000000000111;//原反补一样System.out.println(a);//十进制表示形式7//intb=-7;inta=0b10000000000000000000000000000111;System.out.println(a);//十进制表示形式-2147483641/*如何表示:是负数所以符号位是10b10000000000000000000000000000111?十进制表示是-2147483641并没有显示-7解释:计算机存储有符号数是按照补码的形式存进去的.0b10000000000000000000000000000111不是补码-7是原码总结:1,计算机存储有符号数都是按照补码的形式存储的2,正数的原码,反码,补码都是一样的3,负数的原码,反码,补码不一样,所以如果你直接写intb=-7计算机会帮你把它转成补码存储0b10000000000000000000000000000111这个数据是-7的原码如果你存储这个数据计算机就会把该数据当成补码去存(该数据是-7的原码会被认为是其他数据通过计算之后的补码)原:符号位+数值位(数据的绝对值)反:除了符号位不变其它全部是1变0,0变1补:在反码的基础上+1;再次计算-7原:0b10000000000000000000000000000111反:0b11111111111111111111111111111000补:0b11111111111111111111111111111001//+1*/intb=0b11111111111111111111111111111001;System.out.pirintln(b);//会帮你转换成原码然后再显示十进制-7;/*计算机存的时候是存的0b11111111111111111111111111111001在输出十进制显示的时候要回推成十进制的-71,补码-1得到反码0b11111111111111111111111111111001-10b111111111111111111111111111110002,剩下符号位不变其余1变0,0变10b10000000000000000000000000000111*/
三、位逻辑运算符
1、概念
位运算:(二进制位或者是bit位) 计算机中所有的计算到计算机底层中都会变成位运算(二进制位的运算) 位运算可以提高程序的效率,而且以后我们研究jdk或者某些框架的原码里边有很多地方都会用到位运算
2、分类
双目运算符:连接两个操作数 &: 按位与 规则: 两个同为1时候才为1 |: 按位或 规则: 两个中只要有一个为1结果就是1 ^: 按位异或 规则: 两个中不同为1 相同为0
单目运算符: 操作数只有一个 ~: 按位取反 规则: 1变0,0变1(包括符号位在内)
注意:位运算连接的操作数是--数值类型(二进制) 位运算表达式的结果是--数值类型
1按位与&规则:两个同为1时候才为1//3&4的结果分析:/*1要先转换成二进制位并且全是二进制的补码形式!//正数原反补一样3补码0b000000000000000000000000000000114补码0b000000000000000000000000000001002操作------------------------------------结果0b00000000000000000000000000000000//十进制也就是0*/inta=3&4;System.out.println(a);2按位或|规则:两个中只要有一个为1结果就是1//3|4的结果/*1要先转换成二进制位并且全是二进制的补码形式!//正数原反补一样3补码0b000000000000000000000000000000114补码0b000000000000000000000000000001002操作-----------------------------------结果0b00000000000000000000000000000111//十进制也就是7*/inta=3|4;System.out.pirintln(a);3按位异或^规则:两个中不同为1相同为0//3^4的结果/*1要先转换成二进制位并且全是二进制的补码形式!//正数原反补一样3补码0b000000000000000000000000000000114补码0b000000000000000000000000000001002操作-----------------------------------结果0b00000000000000000000000000000111//十进制也就是7*/inta=3^4;System.out.println(a);一个数据对相同的数据异或两次其值不变a两次异或b结果不变a^b^b==ainta=3;intb=4;System.out.println(a^b^b);/*3补码0b000000000000000000000000000000114补码0b00000000000000000000000000000100--------------------------------------------第一次异或不同为1相同为0结果0b0000000000000000000000000000011140b00000000000000000000000000000100--------------------------------------------第二次异或不同为1相同为00b00000000000000000000000000000011//补码3*/4按位取反1变0,0变1(包括符号位在内)//~3的结果/*1要先转换成二进制位并且全是二进制的补码形式!//正数原反补一样3补码0b000000000000000000000000000000112操作-----------------------------------补码按位取反还是补码结果0b11111111111111111111111111111100//补码//首先符号位是1是负数其次这是补码要算反码现在已知道补码求原码补码:0b11111111111111111111111111111100-1---------------------------------------反码:0b11111111111111111111111111111011//符号位不变取反原码:0b10000000000000000000000000000100//原码十进制显示-4*/inta=~3;System.out.println(a);5互为取反inta=~6;System.out.println(a);//-7//0b00000000000000000000000000000110+6//0b11111111111111111111111111111001取反:结果是负数是补码//0b11111111111111111111111111111000反码//0b10000000000000000000000000000111原码:-(1+2+4)=-7//6取反就是-7那么-7取反呢System.out.println(~-7);//6//0b10000000000000000000000000000111-7原码//0b11111111111111111111111111111000-7反码//0b11111111111111111111111111111001-7补码//0b00000000000000000000000000000110-7取反结果是整数2+4=6
3、案例:数据交互
需求:
已知两个整数变量a = 10,b = 20,使用程序实现这两个变量的数据交换;不允许出现第三方变量
思路:
使用异或,一个数据对相同的数据异或两次其值不变
代码:
publicstaticvoidmain(String[] args){inta =10;intb =20;
a = a ^ b;//a = 10 ^ 20;b = a ^ b;//b = 10 ^ 20 ^ 20;a = a ^ b;//a = 10 ^ 20 ^ 10;System.out.println(a);
System.out.println(b);
}
注意:以后编码中,更多的还是选择定义第三方变量
四、位移运算符
1、分类
位移运算符的分类
<<: 左移 规则:让操作数乘以2的n次幂 n是移动的位数>>: 右移 规则:让操作数除以2的n次幂 n是移动的位数>>>:无符号右移 规则:让操作数除以2的n次幂 n是移动的位数xxxxxxxxxx四、位移运算符 1、分类位移运算符的分类 <<: 左移 规则:让操作数乘以2的n次幂 n是移动的位数 >>: 右移 规则:让操作数除以2的n次幂 n是移动的位数 >>>:无符号右移 规则:让操作数除以2的n次幂 n是移动的位数java
2、左位移操作 <<
规则:让操作数乘以2的n次幂 n是移动的位数
左边符号位丢弃 右边补0格式: 操作数<<往左位移的位数 (操作的是二进制位)inta=3<<2;//操作数 3*2^2 =3*4=12System.out.println(a);/*
补码 0b00000000000000000000000000000011
位移 0b000000000000000000000000000011
右边空出两位补0 左边的两位就被挤掉了
结果:0b00000000000000000000000000001100
符号位是0 是正数 原反补一致
//十进制表示 12
*/负数左移intb=-3<<2;
System.out.println(b);/*
-3
原码 0b10000000000000000000000000000011
反码 0b11111111111111111111111111111100
补码 0b11111111111111111111111111111101
左移 0b111111111111111111111111111101
补齐:0b11111111111111111111111111110100 补码 -1
反码 0b11111111111111111111111111110011
原码 0b10000000000000000000000000001100 原码 1100=-12
*/inti=21;//00000000000000000000000000010101intx1=i<<2;//21*2^2=84 //00000000000000000000000001010100 =4+16+64=84intx2=i<<3;//21*2^3=168 //00000000000000000000000010101000 =8+32+128=168intx3=i<<26;//21*2^26=1409286144 //01010100000000000000000000000000intx4=i<<27;//21*2^27=-1476395008 //10101000000000000000000000000000 变成负数了inti=-21;//10000000000000000000000000010101 原码//11111111111111111111111111101010 反码//11111111111111111111111111101011 补码(反码+1)intx1=i<<2;//-21*2^2=-84//11111111111111111111111111101011 补码//11111111111111111111111110101100 位移补0 求原码//11111111111111111111111110101011 反码//10000000000000000000000001010100 原码 结果是 4+16+64=84 符号是1 结果是-84intx2=i<<3;//-21*2^3=-168intx3=i<<26;//-21*2^26=-1409286144intx4=i<<27;//-21*2^27=1476395008//11111111111111111111111111101011 补码//01011000000000000000000000000000 位移27位 补0 符号位0 变成正数结论: << 在一定的范围内每向左移动移动一位相当于 *2最高效的计算2*82<<3或者8<<1
3、右位移操作 >>
规则:让操作数除以2的n次幂 n是移动的位数
格式: 操作数>>往右位移的位数 (操作的是二进制位)inta=32>>2;//操作数 32/2^2 =32/4=8System.out.println(a);/*
32补码 0b00000000000000000000000000100000
位移 0b000000000000000000000000001000
左边边空出两位补0(符号位是啥补啥) 右边的两位就被挤掉了
结果:0b00000000000000000000000000001000
符号位是0 是正数 原反补一致
//十进制表示 8
*/负数情况intb=-32>>2;//操作数 -32/2^2 =-32/4=-8System.out.println(a);/*
-32原码: 0b10000000000000000000000000100000
取反
反码: 0b11111111111111111111111111011111 (符号位不变 其他1变0 0变1)
+ 1
补码: 0b11111111111111111111111111100000
右位移: 0b111111111111111111111111111000
左边边空出两位补1(符号位是啥补啥 现在符号位是1 补1) 右边的两位就被挤掉了
结果补码:0b11111111111111111111111111111000 //这个也是补码
当输出显示的时候要回推显示原码形式
0b11111111111111111111111111111000
- 1
反码:0b11111111111111111111111111110111
原码:0b10000000000000000000000000001000 //十进制表示 -8
*/inti=21;//00000000000000000000000000010101intx1=i>>2;//00000000000000000000000000000101 1+4=5intx2=i>>3;//00000000000000000000000000000010 2=2;intx3=i>>26;//00000000000000000000000000000000 0intx4=i>>27;//00000000000000000000000000000000 0inti=-21;//10000000000000000000000000010101 原码//11111111111111111111111111101010 反码//11111111111111111111111111101011 补码(反码+1)intx1=i>>2;//11111111111111111111111111101011 补码//11111111111111111111111111111010 右移2位 符号位是啥补啥 已知补码求原码先求反码(补码-1)//11111111111111111111111111111001 反码//10000000000000000000000000000110 //结果是 2+4=6 符号位是1是负数 =-6intx2=i>>3;//-3intx3=i>>26;//-1intx4=i>>27;//-1//11111111111111111111111111101011 补码//11111111111111111111111111111111 右移27位 符号位是啥补啥 已知补码求原码先求反码(补码-1)//11111111111111111111111111111110 反码//10000000000000000000000000000001 结果是 1 符号位是1是负数 =-1结论: >> 在一定的范围内每向右移动移动一位相当于 /2