位操作实现加减乘除四则运算

时间:2022-12-11 15:19:58

位操作实现加减乘除四则运算



1 先来掌握一些常用的位运算操作:

(1)等式:-n = ~(n - 1) = ~n + 1(-n等于其各位取反加1);

(2)获取整数n的二进制中最后一个1:-n&n 或(~n+1)&n或 ~(n - 1)&n

如:n = 010100,则 -n = 101100, n&(n - 1)=000100;

(3)去掉整数n的二进制中最后一个1:n&(n - 1)。如:n = 010100, n -1 = 010011, n&(n - 1) = 010000。


2 四则运算实现

(1)加法(a + b)

用^、&和<<即可实现,a^b可得到对应位没有进位时的和,a&b可得到各位产生的进位值。

如:a=010010, b=100111,计算过程如下:

第一轮:a^b=110101,(a&b)<<1=000100(进位)。由于进位大于0,进入下一轮:a=110101,b=000100;

第二轮:a^b=110001,(a&b)<<1=001000(进位)。进位大于0,进入下一轮:a=110001,b=001000;

第二轮:a^b=111001,(a&b)<<1=000000(进位)。进位等于0,终止;

结果为:111001。


非递归代码如下:

int add(int a, int b)
{
	int carry; // 进位
	while (b)
	{
		carry = (a & b) << 1; // a & b取各位的进位,进位作用于对应位的高1位
		a = a ^ b;
		b = carry;
	}
	return a;
}

递归代码如下:

int add_recursion(int a, int b)
{
	if (0 == b) return a;
	else
	{
		int carry = (a & b) << 1;
		a = a ^ b;
		return add_recursion(a, carry);
	}
}


(2)减法(a - b)

减法可以转化成加法:a - b = a + (-b) = a + (~b + 1)

因此代码如下:

int sub(int a, int b)
{
	return add(a, add(~b, 1));
}


(3)乘法(a * b)

先看一个乘法算法:1011 * 1010

   1011
*  1010
--------
  10110 (1011<<1,相当于乘以0010)
1011000 (1011<<3,相当于乘以1000)
--------
1101110

因此乘法可以通过系列的移位和加法实现。

代码如下:

int mul(int a, int b)
{
	int ans = 0;
	while (b)
	{
		if (b & 1) ans = add(ans, a);
		a <<= 1;
		b >>= 1;
	}
	return ans;
}


(4)除法(a / b)

除法就是由乘法的过程逆推,依次减掉(如果a够减的)b ^ (2 ^ 31), b ^ (2 ^ 30), ...b ^ 8, b ^ 4, b ^ 2, b ^ 1。减掉相应数量的b就在结果加上相应的数量。

1011 / 1010的部分步骤:

 10110000 / 1010
 10110100
-10100000 (1010<<4)
----------
    10100
-   10100 (1010<<1)
----------
        0

代码如下:

int div(int a, int b)
{
	int ans = 0;
	for (int i = 31; i >= 0; i--)
	{
		//比较a是否大于b的(1<<i)次方,避免将a与(b<<i)比较,因为不确定b的(1<<i)次方是否溢出 
		if (b <= (a >> i))
		{
			ans += (1 << i);
			a -= (b << i);
		}
	}
	return ans;
}