我们知道,计算机最基本的操作单元是字节(byte),⼀个字节由8个位(bit)组成,⼀个位只能存储⼀个0或1,其实也就是⾼低电平。⽆论多么复杂的逻辑、庞⼤的数据、酷炫的界⾯,最终体现在计算机最底层都只是对0101的存储和运算。因此,了解位运算有助于提升我们对计算机底层操作原理的理解。 今天就来看看怎么不使⽤显式“ + - * /”运算符来实现加减乘除运算。
下⾯我们⼀个⼀个来看。
1. 加法运算
先来个我们最熟悉的⼗进制的加法运算:snis-110
13 + 9 = 22
我们像这样来拆分这个运算过程:
1. 不考虑进位,分别对各位数进⾏相加,结果为sum: 个位数3加上9为2;⼗位数1加上0为1; 最终结果为12;
2. 只考虑进位,结果为carry:
3 + 9 有进位,进位的值为10;
3. 如果步骤2所得进位结果carry不为0,对步骤1所得sum,步骤2所得carry重复步骤1、 2、3;如果carry为0则结束,最终结果为步骤1所得
舆情终端
无线表决器sum:
这⾥即是对sum = 12 和carry = 10重复以上三个步骤,(a) 不考虑进位,分别对各位数进⾏相加:sum = 22; (b) 只考虑进位: 上⼀步没有进位,所以carry = 0; (c) 步骤2carry = 0,结束,结果为sum = 22.
我们发现这三板斧⾏得通!
那我们现在还使⽤上⾯的三板斧把⼗进制运算放在⼆进制中看看是不是也⾏的通。
13的⼆进制为0000 1101,9的⼆进制为0000 1001:
1. 不考虑进位,分别对各位数进⾏相加:
sum = 0000 1101 + 0000 1001 = 0000 0100
约束椅
2. 考虑进位:
有两处进位,第0位和第3位,只考虑进位的结果为:
carry = 0001 0010
3. 步骤2carry == 0 ?,不为0,重复步骤1 、2 、3;为0则结束,结果为sum:
本例中,
(a)不考虑进位sum = 0001 0110;
(b)只考虑进位carry = 0;
口红管(c)carry == 0,结束,结果为sum = 0001 0110
转换成⼗进制刚好是22.
我们发现,适⽤于⼗进制的三板斧同样适⽤于⼆进制!仔细观察者三板斧,⼤家能不能发现其实第⼀步不考虑进位的加法其实就是异或运算;⽽第⼆部只考虑进位就是与运算并左移⼀位--;第三步就是重复前⾯两步操作直到第⼆步进位结果为0。
这⾥关于第三步多说⼀点。为什么要循环步骤1、 2、 3直到步骤2所得进位carry等于0?其实这是因为有的数做加法时会出现连续进位的情况,举例:3 + 9,我们来⾛⼀遍上述逻辑:
a = 0011,
b = 1001;
start;
first loop;
1.1 sum = 1010
1.2 carry = 0010
1.3 carry != 0 , go on;
second loop;
2.1 sum = 1000;
打包交易2.2 carry = 0100;
2.3 carry != 0, go on;
third loop;
3.1 sum = 1100;
3.2 carry = 0000;
3.3 carry == 0, stop; result = sum;
end
如上⾯的栗⼦,有的加法操作是有连续进位的情况的,所以这⾥要在第三步检测carry是不是为0,如果为0则表⽰没有进位了,第⼀步的sum即为最终的结果。
有了上⾯的分析,我们不难写出如下代码: