如何计算二进制补码的有效位数:关于二进制的计算方法和原码
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
*/
位运算:(二进制位或者是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
需求:
已知两个整数变量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的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
规则:让操作数除以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
,
免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com