数字在计算机中的表示
首先,数字在计算机中的表示形式跟我们平常书面上的表示形式不同,
原码就是符号位加上真值的绝对值,即用第一位表示符号,其余位表示值,比如如果是8位二进制:
[+1]原=0000 0001 [-1]原=1000 0001
反码的表示方法是:正数的反码是其本身,而负数的反码是在其原码的基础上,符号位不变,其余各个位取反。例如:
[+1]=[00000001]原 = [00000001]反 [-1]=[10000001]原 = [11111110]反
补码
-
正数的补码就是其本身:
-
负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1(即在反码的基础上+1)。
[+1]=[00000001]原=[00000001]反=[00000001]补 [-1]=[10000001]原=[11111110]反=[11111111]补
与 或 异或 和 取反
与运算的符号是&,运算规则是:对于每个二进制位,当两个数对应的位都为1时,结果才为1,否则结果为0。
0 & 0 = 0 0 & 1 = 0 1 & 0 = 0 1 & 1 = 1
或运算的符号是,运算规则是:对于每个二进制位,当两个数对应的位都为0时,结果才为0,否则结果为1。
0 | 0 = 0 0 | 1 = 1 1 | 0 = 1 1 | 1 = 1
异或运算的符号是⊕(在代码中用^表示异或),运算规则是:对于每个二进制位,当两个数对应的位相同时,结果为0,否则结果为1。
0 ⊕ 0 = 0 0 ⊕ 1 = 1 1 ⊕ 0 = 1 1 ⊕ 1 = 0
取反运算的符号是~,运算规则是:对一个数的每个二进制位进行取反操作,0变成1,1变成0。
~0=1 ~1=0
而如何获取、设置和更新某个位的数据,也有固定的套路。例如:
-
获取
该方法是将1左移位,得到形如00010000的值。接着对这个值与num执行” 位与 “操作,从而将i位之外的所有位清零,最后检查该结果是否为零。不为零说明i位为1,否则i位为0。代码如下:
boolean getBit(int num, int i) { return ((num & (1 << i)) != 0); }
-
设置
setBit先将1左移i位,得到形如00010000的值,接着堆这个值和num执行” 位或 “操作,这样只会改变位的数据。这样除位外的位均为零,故不会影响num的其余位。代码如下:
int setBit(int num, int i) { return num | (1 << i); }
-
清零
该方法与setBit相反,首先将1左移i位获得形如00010000的值,对这个值取反进而得到类似11101111的值,接着对该值和num执行” 位与 “,故而不会影响到num的其余位,只会清零i位。
int clearBit(int num, int i) { int mask = ~(1 << i); return num & mask; }
-
更新
这个方法是将setBiti和clearBit合二为一,首先用诸如11101111的值将num的第i位清零。接着将待写入值v左移i位,得到一个i位为v但其余位都为0的数。最后对之前的结果执行” 位或 “操作,v为1这num的i位更新为1,否则为0:
int updateBit(int num, int i, int v) { int mask = ~(1 << i); return (num & mask) | (v << i); }