二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”。当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的。

原码、反码和补码

原码:一个整数,按照绝对值大小转换成的二进制数,最高位为符号位,称为原码。例如: 00000000 00000000 00000000 00000101 是 5的 原码;10000000 00000000 00000000 00000101 是-5的原码。

反码:将二进制数除符号位外按位取反,得到的新二进制数称为原二进制数的反码。正数的反码为原码,负数的反码除符号位外按位取反。例如:十进制5的二进制原码为00000000 00000000 00000000 00000101,其反码与原码相同;十进制-5的二进制原码为10000000 00000000 00000000 00000101,其反码为11111111 11111111 11111111 11111010。

补码:正数的补码为原码,负数的补码为反码+1。例如:十进制-5的二进制原码为10000000 00000000 00000000 00000101,反码为11111111 11111111 11111111 11111010,补码为11111111 11111111 11111111 11111011。

直接用原码计算有时会出现计算错误,例如:

1 - 1 = 0
00000001 + 10000001= 10000010 = -2

用反码可以解决以上问题:

1 - 1 = 0
00000001+ 11111110 = 11111111 = -0

但出现了正负零问题,补码出现的原因就是为了解决正负零问题,例

1 - 1 = 0
00000001 + 11111111 = 00000000 = 0

因此,计算机中的计算都是用的补码。

有符号数和无符号数

二进制中存在有符号数和无符号数两种。有符号数中,二进制的最高位为符号位,0为正数,1为负数,例如:0111 1111的值为127,-1000 0000的值为-128,1byte即1个字节(8bit),因此1byte的取值为-128 ~ 127。而无符号数中,所有的位数都用来表示该数值,因此8位无符号数能表示的范围为0~255。

负数二进制转换十进制

  1. 对二进制按位取反;
  2. 对取反后的二进制+1;
  3. 转换成十进制,并在前面加-号。

位运算

  1. &与运算:两个数二进制对应的位都为1,该位的结果为1,否则为0。例如3&10即0000 0011 & 0000 1010 = 0000 0010 = 2;
  2. |或运算:两个数二进制对应的位任一个为1,该位的结果为1,否则为0。例如3|10即0000 0011 | 0000 1010 = 0000 1011 = 11;
  3. ~取反运算:单目运算符,将二进制中为1的变为0,为0的变为1。例如~3 = ~(0000 0011) = 1111 1100 = -4;
  4. ^异或运算:两个数二进制对应的位相同则为0,不同则为1。例如3^10即0000 0011 ^ 0000 1010 = 0000 1001 = 9;
  5. >>右移运算:运算符左边的数的二进制右移运算右边的数的大小个位数。例如a>>b表示a的二进制右移b个位数,其中当a是正数时,高位补0,a是负数时,高位补1;
  6. a << b:a的二进制表示左移b位,低位补0。因符号位会被移出去,可能会出现正数左移变负数,负数变正数。且当左移的位数超过该数据类型的最大位数时,编译器会用左移位数模该数据类型的最大位数,然后用余数作为左移的位数;
  7. a >>> b:a无符号右移b位,高位补0。

相关API

Integer包装类有将十进制int转换为二进制、八进制以及十六进制的方法。

//转换为32位的二进制,对于负数返回的是其补码
public static String toBinaryString(int i);
//转换为八进制
public static String toOctalString(int i);
//转换为十六进制
public static String toHexString(int i);

同样有将其他进制转换为十进制的方法,其实就是我们熟知的parseInt()和valueOf()方法,但是它们的重载方法,多了一个“进制”参数。

//将其他进制转换为十进制,返回Integer对象
public static Integer valueOf(String s, int radix) throws NumberFormatException;
//将其他进制转换为十进制,返回int
public static int parseInt(String s, int radix) throws NumberFormatException;

测试程序

public static void main(String[] args) {
    System.out.println("***二进制***");
    System.out.println(Integer.toBinaryString(-5));
    System.out.println(Integer.valueOf("-101",2));
    System.out.println(Integer.parseInt("-101",2));
    System.out.println("***十六进制***");
    System.out.println(Integer.toHexString(65535));
    System.out.println(Integer.valueOf("FFFF",16));
    System.out.println(Integer.parseInt("FFFF",16));
}

输出结果

***二进制***
11111111111111111111111111111011
-5
-5
***十六进制***
ffff
65535
65535