1.位运算
程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作。比如,and运算本来是一个逻辑运算符,但整数与整数之间也可以进行and运算。举个例子,6的二进制是110,11的二进制是1011,那么6 and 11的结果就是2,它是二进制对应位进行逻辑运算的结果(0表示False,1表示True,空位都当0处理)。
我们可以知道计算机的底层是二进制,在进行数的加减时,是通过转换成二进制,进行位运算来求值的,这显然是行得通的。
2.位运算实现加法运算:
1.十进制的加法运算:13 + 9 = 22。拆分运算过程:
①不考虑进位,分别对各位数进行相加,结果为 sum(1):个位数 3 加上 9 为 2,十位数 1 加上 0 为 1;最终结果为 12;
②只考虑进位,结果为 carry(1):3 + 9 有进位,进位的值为 10;
③如果步骤 ② 所得进位结果 carry 不为 0,对步骤 ① 所得 sum(1),步骤 ②所得 carry(1) 重复步骤 ①、②、③;如果 carry(n) 为 0 则结束,最终结果为步骤 ① 所得 sum(n) :
α:对 sum(1) = 12 和 carry(1) = 10 重复以上三个步骤:不考虑进位:sum(2) = 22;只考虑进位:carry(2) = 0;carry(2) = 0,结束;sum(2) = 22。
2.二进制的加法运算:13 的二进制为 0000 1101,9 的二进制为 0000 1001:00001101 + 00001001 = 0001 0110;拆分运算过程:
①不考虑进位:sum(1) = 0000 1101 + 0000 1001 = 0000 0100;
②考虑进位:有两处进位,第 0 位和第 3 位,只考虑进位的结果为:carry(1) = 0001 0010;
③步骤 ② carry(1) 不为 0,重复步骤 ①、②、③;carry(n) 为 0 则结束,结果为 sum(n):
α:不考虑进位 sum(2) = 0001 0110;只考虑进位:carry(2) = 0;carry(2) = 0,结束,最终结果为 sum(2) = 0001 0110。
3.第一步不考虑进位的加法其实就是异或运算;第二步只考虑进位就是 与运算并左移一位;第三步就是重复前面两步操作直到第二步进位结果为 0。
4.代码实现:可以通过迭代和递归。
1.递归:
#include<stdio.h>
int main(){
int a,b;
scanf("%d %d",&a,&b);
int sum=add(a,b);
printf("%d",sum);
}
int add(int a,int b){
if(b==0){
return a;
}
int sum=a^b;
int carry=(a&b)<<1;
return add(sum,carry);
}
2.迭代:
#include<stdio.h>
int main(){
int a,b;
scanf("%d %d",&a,&b);
int sum=add(a,b);
printf("%d",sum);
}
int add(int a,int b){
int sum,carry;
do{
sum=a^b;
carry=(a&b)<<1;
a=sum;
b=carry;
} while(carry!=0);
return sum;
}
3.位运算实现减法
应为数在计算机中都是以补码的形式储存的,正数的补码和反码是本身,负数的补码是负数取反再加一
例如:
【+1】= 原: [ 0000 0001 ] = 反:[ 0000 0001 ] = 补:[ 0000 0001 ]
【-1】 = 原:[ 1000 0001 ] = 反:[ 1111 1110 ] = 补:[ 1111 1111 ]
相比较上面而言多加上一个求补码的操作。
int minus(int a, int b)
{
return add(a, add(~b, 1));
}