【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
【4】>>(<<)和>>>(<<<)
① >>
有符号按位右移运算符。左操作数按位右移右操作数指定的位数,符号位不变,空出来的高位补符号位
。
输入1个参数b;n = 1;b为负数,第一个位符号位为1。
b对应位全部右移动n位得到c;b最右边n个位全部丢掉(红色框),c最左边n个位补充1(绿色框)。
这里需要注意的是其左边补充的值取决于b的最高位也就是符号位:符号位是1则补充1,符号位是0则补充0。
② >>>
无符号按位右移运算符。左操作数按位右移右操作数指定的位数,符号位跟着移动
,空出来的高位补0
(左边补充的值永远为0,不管其最高位(符号位)的值)。
测试如下:
@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
输入2个参数,a、b对应位都为1时,c对应位为1;反之为0。
② 按位或 a | b
输入2个参数,a、b对应位只要有一个为1,c对应位就为1;反之为0。
③ 按位异或 a^b
输入2个参数,a、b对应位只要不同,则c对应位就为1;反之为0。
④ 按位取反(非)
输入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】:
注意:计算机存放数字都是存放数字的补码,正数的原码、补码、反码都一样,负数的补码是其反码加一。符号位做取反操作时不变,做逻辑与、或、非、异或操作时要参与运算。