0%

Java基础之二进制位运算

原码、反码、补码
java位运算
进制的转换

1 原码、反码、补码

计算机数据的以二进制储存和传输,而物理电路只能识别0和1,那么负数应该如何表示?

数据分为无符号整型有符号整形两种。无符号整型只能表示正数,简单明了直接以原码存储;有符号整型最高位表示数的符号,最高位为1表示为负数,最高位为0表示正数,其余位则表示数值。这也是为什么相同字节数的有符号整型的范围比无符号整型要少将近一倍的原因。

下面先给出原码、补码、反码的概念(以一个字节的有符号整型为例):

原码:数据直接的二进制表示,如+1:0000 0001;-1:1000 0001;如+127:0111 1111;-127:1111 1111。显而易见,原码不能直接相加,相反数相加不为0;

反码:正数的反码与原码相同,负数的反码为其原码的绝对值按位求反,或者说符号位(最高位)保持不变,其他位按位求反,如:+1:0000 0001;-1:1111 1110;如+127:0111 1111;-127:1000 0000。再显而易见,这次相反数相加没问题了,但是部分运算仍可能溢出,如-1 + (+2)= (+1),but (1111 1110 +0000 0010 = 0000 0000),溢出之后全部置零,结果为0出错。

补码:正数的补码也和原码相同,负数的补码等于其反码+1,如+1 : 0000 0001;-1:1111 1111;如+127:0111 1111;-127:1000 0001。不是很显而易见,但是用补码做计算木有问题。

使用补码计算的好处是利用补数和溢出的原理,将减法变为加法,避免溢出,使计算正确,所以计算机有符号整型计算使用的是补码。具体的补数的原理以后还有深究、这里先暂时记下结论。

十进制 原码 反码 补码
+1 0000 0001 0000 0001 0000 0001
-1 1000 0001 1111 1110 1111 1111
+127 0111 1111 0111 1111 0111 1111
-127 1111 1111 1000 0000 1000 0001

2 java位运算

1
2
3
4
5
6
7
&: 按位与。当两位同时为1 时才返回1。
|: 按位或。只要有一位为1 即可返回1。
~: 按位非。单目运算符,将操作数的每个位(包括符号位)全部取反。
^: 按位异或。当两位相同时返回0 , 不同时返回1。
<<: 左移运算符。
>>: 右移运算符。
>>>: 无符号右移运算符。

只简单的说一下移位运算符:

左移运算符<<:例:x<<n,将数x的二进制表示左移n位,直接扔掉前n位,后面补n个0。

右移运算符>>: 例:x>>n,将数x的二进制表示右移n位,前面补上n位符号位(正数补n个0,负数补n个1),再直接扔掉后面n位。

无符号右移运算符>>>:前面加n个0,后面扔掉n位数。

整型的移位运算都是基于32位表示的(4个字节),左移或右移32位就相当于没有移。总结来说就是移位之前要对32取余,所得的余数是要移动的位数。

3 十进制和其他进制的转换

n&(n-1) 可以减去n的最后一个1

n & 0x1 表示k与0x1按位与,其效果为取k的二进制中最右边的数字(和n&1效果相同)

int temp = n & 0xf; // 取低4位的十进制值 (和n&15效果相同)

10进制转16进制

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public String toHex(int num) {
if(num == 0) return "0";
StringBuilder res = new StringBuilder();
char[] ch = "0123456789abcdef".toCharArray();
while(num!=0){
int temp = num & 15; //取num后四位对应的10进制数
res.append(ch[temp]);
num = num >>> 4;
}
return res.reverse().toString(); //是从低位开始转换 需要reverse反转以下
}
}

10进制转2进制

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public String toHex(int num) {
if(num == 0) return "0";
StringBuilder res = new StringBuilder();
char[] ch = "01".toCharArray();
while(num!=0){
int temp = num & 1; //取num后1位对应的10进制数
res.append(ch[temp]);
num = num >>> 1;
}
return res.reverse().toString(); //是从低位开始转换 需要reverse反转以下
}
}

内置函数

1
2
3
4
String hexString = Integer.toHexString(int decNum); //10转16
String octalString = Integer.toOcalString(int decNum); //10转8
String binaryString = Integer.toBinaryString(int decNum); //10转2
String decStr = Integer.parseInt(String nStr,int n); // n进制转10
-------------感谢阅读没事常来-------------