如何计算二进制补码的有效位数:关于二进制的计算方法和原码

原码、反码、补码

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、无符号右移: >>>

如何计算二进制补码的有效位数:关于二进制的计算方法和原码(1)

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页