关于二进制的计算方法和原码、反码、补码等操作

原码、反码、补码

1 什么是原码反码补码
按照二进制进行存储
运算:按照二进制补码方式参与运算

原码:通过8421码快速计算数据大小(推荐使用计算器) 直观的看数据的大小
反码:在转换补码的过程中的中间值
补码:参与运算

2 有符号数表示法怎么做
有符号数:数据有正负之分就是有符号数, 数据无正负之分就是无符号数
例如: +7 -7

有符号数的组成: 符号位+数值位
例如 int a=+7; 所占字节数4b 32位 第一个0就是符号位 0表示正数 1表示负数
0 0000000 00000000 00000000 00000111

回顾: int表示范围 2的32次方个数
-2的31次方 到 +2的31次方-1 //有一位是符号位 所以31次方

那么+7 和 -7在计算机中如何存储

代码表示:
//int a=+7;
int a=0b00000000000000000000000000000111; //原反补 一样
System.out.println(a); //十进制表示形式 7

//int b=-7;
int a=0b10000000000000000000000000000111;
System.out.println(a);//十进制表示形式 -2147483641
/*
如何表示: 是负数所以符号位是1
0b10000000000000000000000000000111 ?
十进制表示是 -2147483641 并没有显示-7

解释:计算机存储有符号数是按照补码的形式存进去的.
0b10000000000000000000000000000111 不是补码 -7是原码

总结:
1,计算机存储有符号数都是按照补码的形式存储的
2,正数的原码,反码,补码都是一样的
3,负数的原码,反码,补码不一样,

所以如果你直接写int b=-7 计算机会帮你把它转成补码存储
0b10000000000000000000000000000111这个数据是-7的原码
如果你存储这个数据计算机就会把该数据当成补码去存
(该数据是-7的原码 会被认为是其他数据通过计算之后的补码)

原: 符号位+数值位(数据的绝对值)
反: 除了符号位不变 其它全部是1变0,0变1
补: 在反码的基础上+1;

再次计算-7
原: 0b10000000000000000000000000000111
反: 0b11111111111111111111111111111000
补: 0b11111111111111111111111111111001 //+1

*/
int b=0b11111111111111111111111111111001;
System.out.pirintln(b);// 会帮你转换成原码然后再显示十进制 -7;
/*
计算机存的时候是存的0b11111111111111111111111111111001
在输出十进制显示的时候要回推成十进制的-7
1,补码-1 得到反码
0b11111111111111111111111111111001
-1
0b11111111111111111111111111111000
2,剩下符号位不变其余 1变0,0变1
0b10000000000000000000000000000111
*/

三、位逻辑运算符

1、概念

位运算:(二进制位或者是bit位) 计算机中所有的计算到计算机底层中都会变成位运算(二进制位的运算) 位运算可以提高程序的效率,而且以后我们研究jdk或者某些框架的原码里边有很多地方都会用到位运算

2、分类

双目运算符:连接两个操作数 &: 按位与 规则: 两个同为1时候才为1 |: 按位或 规则: 两个中只要有一个为1结果就是1 ^: 按位异或 规则: 两个中不同为1 相同为0

单目运算符: 操作数只有一个 ~: 按位取反 规则: 1变0,0变1(包括符号位在内)

注意:位运算连接的操作数是--数值类型(二进制) 位运算表达式的结果是--数值类型

1 按位与 & 规则: 两个同为1时候才为1
// 3 & 4 的结果
分析:
/*
1 要先转换成二进制位 并且全是二进制的补码形式! //正数原反补 一样
3 补码 0b00000000000000000000000000000011
4 补码 0b00000000000000000000000000000100
2 操作 ------------------------------------
结果0b00000000000000000000000000000000 //十进制也就是0

*/
int a=3&4;
System.out.println(a);

2 按位或 | 规则: 两个中只要有一个为1结果就是1
// 3 | 4 的结果
/*
1 要先转换成二进制位 并且全是二进制的补码形式! //正数原反补 一样
3 补码 0b00000000000000000000000000000011
4 补码 0b00000000000000000000000000000100
2 操作 -----------------------------------
结果 0b00000000000000000000000000000111 //十进制也就是7

*/
int a=3|4;
System.out.pirintln(a);

3 按位异或 ^ 规则: 两个中不同为1 相同为0
// 3 ^ 4 的结果
/*
1 要先转换成二进制位 并且全是二进制的补码形式! //正数原反补 一样
3 补码 0b00000000000000000000000000000011
4 补码 0b00000000000000000000000000000100
2 操作 -----------------------------------
结果 0b00000000000000000000000000000111 //十进制也就是7

*/
int a=3^4;
System.out.println(a);

一个数据对相同的数据异或两次其值不变
a两次异或b结果不变
a^b^b==a

int a=3;
int b=4;
System.out.println(a^b^b);

/*
3 补码 0b00000000000000000000000000000011
4 补码 0b00000000000000000000000000000100
-------------------------------------------- 第一次异或不同为1 相同为0
结果 0b00000000000000000000000000000111
4 0b00000000000000000000000000000100
--------------------------------------------第二次异或不同为1 相同为0
0b00000000000000000000000000000011 //补码 3
*/

4 按位取反 1变0,0变1(包括符号位在内)
// ~3 的结果
/*
1 要先转换成二进制位 并且全是二进制的补码形式! //正数原反补 一样
3 补码 0b00000000000000000000000000000011
2 操作 -----------------------------------补码按位取反还是补码
结果 0b11111111111111111111111111111100 //补码
//首先符号位是1 是负数 其次 这是补码 要算反码

现在已知道补码求原码
补码:0b11111111111111111111111111111100
- 1
---------------------------------------
反码:0b11111111111111111111111111111011 //符号位不变 取反
原码:0b10000000000000000000000000000100 //原码 十进制显示 -4
*/
int a=~3;
System.out.println(a);

5 互为取反
int a = ~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,使用程序实现这两个变量的数据交换;不允许出现第三方变量

思路:

使用异或,一个数据对相同的数据异或两次其值不变

代码:

public static void main(String[] args) {
int a = 10;
int b = 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
格式: 操作数<<往左位移的位数 (操作的是二进制位)
int a=3<<2; //操作数 3*2^2 =3*4=12
System.out.println(a);
/*
补码 0b00000000000000000000000000000011
位移 0b000000000000000000000000000011
右边空出两位补0 左边的两位就被挤掉了
结果:0b00000000000000000000000000001100
符号位是0 是正数 原反补一致
//十进制表示 12
*/

负数左移
int b=-3<<2;
System.out.println(b);
/*
-3
原码 0b10000000000000000000000000000011
反码 0b11111111111111111111111111111100

补码 0b11111111111111111111111111111101
左移 0b111111111111111111111111111101

补齐:0b11111111111111111111111111110100 补码 -1
反码 0b11111111111111111111111111110011
原码 0b10000000000000000000000000001100 原码 1100=-12
*/

int i=21; //00000000000000000000000000010101
int x1=i<<2; //21*2^2=84 //00000000000000000000000001010100 =4+16+64=84
int x2=i<<3; //21*2^3=168 //00000000000000000000000010101000 =8+32+128=168
int x3=i<<26;//21*2^26=1409286144 //01010100000000000000000000000000
int x4=i<<27;//21*2^27=-1476395008 //10101000000000000000000000000000 变成负数了

int i=-21;
//10000000000000000000000000010101 原码
//11111111111111111111111111101010 反码
//11111111111111111111111111101011 补码(反码+1)

int x1=i<<2; //-21*2^2=-84
//11111111111111111111111111101011 补码
//11111111111111111111111110101100 位移补0 求原码
//11111111111111111111111110101011 反码
//10000000000000000000000001010100 原码 结果是 4+16+64=84 符号是1 结果是-84

int x2=i<<3; //-21*2^3=-168
int x3=i<<26;//-21*2^26=-1409286144
int x4=i<<27;//-21*2^27=1476395008
//11111111111111111111111111101011 补码
//01011000000000000000000000000000 位移27位 补0 符号位0 变成正数
结论: << 在一定的范围内每向左移动移动一位相当于 *2


最高效的计算 2*8
2<<3 或者 8<<1

3、右位移操作 >>

规则:让操作数除以2的n次幂 n是移动的位数
格式: 操作数>>往右位移的位数 (操作的是二进制位)
int a=32>>2; //操作数 32/2^2 =32/4=8
System.out.println(a);
/*
32补码 0b00000000000000000000000000100000
位移 0b000000000000000000000000001000
左边边空出两位补0(符号位是啥补啥) 右边的两位就被挤掉了
结果:0b00000000000000000000000000001000
符号位是0 是正数 原反补一致
//十进制表示 8
*/

负数情况
int b=-32>>2; //操作数 -32/2^2 =-32/4=-8
System.out.println(a);

/*
-32原码: 0b10000000000000000000000000100000
取反
反码: 0b11111111111111111111111111011111 (符号位不变 其他1变0 0变1)
+ 1
补码: 0b11111111111111111111111111100000

右位移: 0b111111111111111111111111111000
左边边空出两位补1(符号位是啥补啥 现在符号位是1 补1) 右边的两位就被挤掉了
结果补码:0b11111111111111111111111111111000 //这个也是补码

当输出显示的时候要回推显示原码形式
0b11111111111111111111111111111000
- 1
反码:0b11111111111111111111111111110111
原码:0b10000000000000000000000000001000 //十进制表示 -8

*/
int i=21; //00000000000000000000000000010101
int x1=i>>2; //00000000000000000000000000000101 1+4=5
int x2=i>>3; //00000000000000000000000000000010 2=2;
int x3=i>>26;//00000000000000000000000000000000 0
int x4=i>>27;//00000000000000000000000000000000 0


int i=-21;
//10000000000000000000000000010101 原码
//11111111111111111111111111101010 反码
//11111111111111111111111111101011 补码(反码+1)

int x1=i>>2;
//11111111111111111111111111101011 补码
//11111111111111111111111111111010 右移2位 符号位是啥补啥 已知补码求原码先求反码(补码-1)
//11111111111111111111111111111001 反码
//10000000000000000000000000000110 //结果是 2+4=6 符号位是1是负数 =-6
int x2=i>>3; //-3
int x3=i>>26; //-1
int x4=i>>27; //-1
//11111111111111111111111111101011 补码
//11111111111111111111111111111111 右移27位 符号位是啥补啥 已知补码求原码先求反码(补码-1)
//11111111111111111111111111111110 反码
//10000000000000000000000000000001 结果是 1 符号位是1是负数 =-1

结论: >> 在一定的范围内每向右移动移动一位相当于 / 2

4、无符号右移: >>>

展开阅读全文

页面更新:2024-03-14

标签:反码   补码   操作   正数   负数   位移   计算方法   符号   形式   规则   数据

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top