0
点赞
收藏
分享

微信扫一扫

JavaSE - 原码,反码,补码和>>以及>>>

【1】原码

原码表示法是机器数的一种简单表示法。

其符号位用0表示正数,用1表示负数,数值一般用二进制形式表示。

  • [x]原=符号位+绝对值
x=+1100110       [x]原=01100110   
x= -1100110 [x]原=11100110

所以用8位二进制数来表示整数原码时,其表示范围: 最大数:01111111,为(+127)D 最小数:11111111,为(-127)D

【2】反码

机器数的反码可由原码得到。

如果机器数是正数,则机器数的反码与原码一致;

若机器数是负数,则机器数的反码是它的原码(符号位除外)的各位取反而得到。

即:

正数:[x]反=[x]原

负数:[x]反=对[x]原除符号外的各位取反

x=+1100110       [x]反=01100110  ;
x= -1100110 [x]反=10011001

【3】补码

机器数的补码也可由原码得到。

如果机器数是正数,则机器数的补码与原码一致。

若机器数是负数,则机器数的补码是它的原码(符号位除外)的各位取反,并在末位加1而得到。即:反码是作为求补码的中间过程。

  • 正数:

[x]补=[x]原

  • 负数:

[x]补=[x]反+1

x=+1100110       [x]补=01100110  
x=-1100110 [x]补=10011010

注意:补码的0只有一种表示形式!

[+0]原=00000000    [-0]原=10000000 
[+0]反=00000000 [-0]反=11111111
[+0]补=[-0]补=00000000

所以用8位二进制数来表示整数补码时,其表示范围: 最大数:01111111,为(+127)D 最小数:10000000,为(-128)D

这里需要特别注意的是,计算机是以有符号的补码的形式存储数据,最高位为符号位,在运算过程中符号位并无差别也直接当作普通值进行步进运算!

如下所示,分别打印byte类型的正数和负数:

byte a=33;
byte b1=-3;
System.out.println(Integer.toBinaryString(a&0xFF));
System.out.println(Integer.toBinaryString(b1&0xFF));

结果如下:

100001
11111101

JavaSE - 原码,反码,补码和>>以及>>>_补码

【4】>>(<<)和>>>(<<<)

① >>

有符号按位右移运算符。左操作数按位右移右操作数指定的位数,​​符号位不变,空出来的高位补符号位​​​。
JavaSE - 原码,反码,补码和>>以及>>>_十进制_02
输入1个参数b;n = 1;b为负数,第一个位符号位为1。

b对应位全部右移动n位得到c;b最右边n个位全部丢掉(红色框),c最左边n个位补充1(绿色框)。

这里需要注意的是其左边补充的值取决于b的最高位也就是符号位:符号位是1则补充1,符号位是0则补充0。

② >>>

无符号按位右移运算符。左操作数按位右移右操作数指定的位数,​​符号位跟着移动​​​,​​空出来的高位补0​​​(左边补充的值永远为0,不管其最高位(符号位)的值)。
JavaSE - 原码,反码,补码和>>以及>>>_十进制_03

测试如下:

@Test
public void testFuHao(){
int a = 6;
int b = -6;
System.out.println(a+","+Integer.toBinaryString(a) );//110
int i1 = a>>2;
System.out.println(i1+","+Integer.toBinaryString(i1) );//1
int i2 = a>>>2;
System.out.println(i2+","+Integer.toBinaryString(i2) );//1
System.out.println("*********************************************************");
System.out.println(b+","+Integer.toBinaryString(b) );//
int i = b>>2;
System.out.println(i+","+Integer.toBinaryString(i));//
int j = b>>>2;
System.out.println(j+","+Integer.toBinaryString(j));//
}

结果输出如下:

6,110
1,1
1,1
*********************************************************
-6,11111111111111111111111111111010
-2,11111111111111111111111111111110
1073741822,111111111111111111111111111110

正数,原码、反码和补码一致。

负数计算就稍微麻烦一点,根据上面所讲的计算方法很快可以验证结果。

最后一个数据,只有30位,前面00没有展示出来。

当b>>>2之后,补码形式为正数,转为十进制为2^30-2=1073741822。

为什么是32位???

因为是 int !

【5】& | ^ 和取反

假设a b(注意是补码形式)如下:

byte a = (byte)0b01011000 //88
byte b = (byte)0b10101000 // -88

① 按位与 a & b
JavaSE - 原码,反码,补码和>>以及>>>_反码_04
输入2个参数,a、b对应位都为1时,c对应位为1;反之为0。

② 按位或 a | b
JavaSE - 原码,反码,补码和>>以及>>>_十进制_05
输入2个参数,a、b对应位只要有一个为1,c对应位就为1;反之为0。

③ 按位异或 a^b
JavaSE - 原码,反码,补码和>>以及>>>_反码_06
输入2个参数,a、b对应位只要不同,则c对应位就为1;反之为0。

④ 按位取反(非)
JavaSE - 原码,反码,补码和>>以及>>>_十进制_07
输入1个参数,c对应位与输入参数a完全相反;a对应位为1,则c对应位就为0;a对应位为0,则c对应位就为1。

【6】进制表示规范

① 前缀

  • 十进制:直接写数字即可
  • 二进制:0b或0B开头;如:0b01011000 代表十进制 88
  • 八进制:0开头;如:0130 代表十进制 88 (1x64+3x8)
  • 十六进制:0x或0X开头;如:0x58 代表 88 (5x16+8)

② 后缀

  • 0x?? 若小于127 则按byte算,大于则按int类型算
  • 0xFF默认为int类型
  • 若声明为long添加后缀:L或l:如:0xFFL 或 0xFFl
  • 带小数的值默认为double类型;如:0.1
  • 若声明为float添加后缀:f 或 F:如:0.1F
  • 若声明为double添加后缀:d或D:如:1D

③ 范围

  • 二进制:1、0
  • 八进制:0~7
  • 十进制:0~9
  • 十六进制:0~9 + A~F

【Tips】:

注意:计算机存放数字都是存放数字的补码,正数的原码、补码、反码都一样,负数的补码是其反码加一。符号位做取反操作时不变,做逻辑与、或、非、异或操作时要参与运算。


举报

相关推荐

0 条评论