1.基本概念——原码、反码、补码
原码:正数和负数的原码是它本身。例如一个8位的二进制数。最高位表示符号位,即正负号。00001000表示10进制的8。10001000表示这是一个负数,这里,并没有说这个数代表10进制的哪个数。因为在计算机中负数不是用原码表示的,后面会解释。
反码:正数的反码和原码相同。负数的反码按位取反,符号位不变,如10001000的反码为11110111。反码其实是专门为补码而存在的,是补码的一个步骤,见补码的说明。
补码:在反码的基础上尾部加1。10001000的反码为11110111,加1就是11111000。
为什么要用补码来表示负数?
因为计算机不支持减法操作。如3-2,减去一个数等于加上这个数的负数,3-2=3+(-2)。计算机设计成只支持加法,是为了简化电路的设计,如果设计成支持减法,电路会变得复杂。
下面给出Java实例。
例一:
int i=-1;
System.out.println(Integer.toBinaryString(i));
11111111111111111111111111111111
Process finished with exit code 0
可以看到-1在计算机中的表示是以补码的形式存在的。因为int占4个字节,所以原码如下这样。
原码:100000000 00000000 00000000 00000001
反码:11111111 11111111 11111111 11111110
补码:11111111 11111111 11111111 11111111
2.Java数据类型占用字节
既然涉及到字节,就要先理清楚java各个数据类型占用的字节数。
int:4个字节。
char:2个字节。在《Java核心编程》里面提到,char是采用utf-16编码的,16位所以占用两个字节。
short:2个字节。
long:8个字节。
float:4个字节。
double:8个字节
boolean:1个字节
byte:1个字节
如何在java中表示一个二进制数?
在java中通过前缀0b(是零不是字母o),0x,0分别表示二进制数,十六进制,八进制。
他们都是int类型的。可以强转为其他类型。
int i16=0xffffffff;//一个int型16进制数
int i8=06777;//一个int型8进制数
int i2=0b11111111111111111111111111111111;//一个int型2进制数
long long16=0xffffffff;//int类型强转为long类型
//输出十进制
System.out.println(Integer.toString(i2));
-1
Process finished with exit code 0
结果是正确的,为-1。
3.按位操作符
按位操作符有4个:~(取反),&(与),|(或),^(异或)。
int i=0b1001;
int j=0b1111;
//取反
System.out.println(Integer.toBinaryString(~i));
//与
System.out.println(Integer.toBinaryString(i&j));
//或
System.out.println(Integer.toBinaryString(i|j));
//异或
System.out.println(Integer.toBinaryString(i^j));
11111111111111111111111111110110
1001
1111
110
Process finished with exit code 0
分析:
第一个输出结果:int i=0b1001,补全为00000000 00000000 00000000 00001001。取反结果为11111111111111111111111111110110。
第二个输出结果:对应位都为1取1,否则取0。
第三个输出结果:对应位都为0取0,否则取1。
第四个输出结果:都为1或都为0取0,其它取1。