如何只用逻辑运算实现算术加减乘除运算

本文介绍如何仅使用逻辑运算实现加法、减法、乘法和除法运算。通过对二进制加法特点的分析,利用异或运算和进位运算实现了加法;通过将减法转换为加法实现减法;通过位运算特性实现乘法;并介绍了两种实现除法的方法。
      我们知道,在逻辑代数中,有与、或、非三种基本逻辑运算。通过三种基本逻辑运算之间的组合运算,又可以构造出与非、或非、异或等常用运算。我们在编写计算机代码的时候,通过加减乘除运算符可以很容易地实现该基本运算,但是我们如何使用逻辑运算来实现算术加减乘除基本运算呢?


      1、如何只用逻辑运算实现加法运算

      在实现代码之前,我们先来分析一下加法的运算特点。例如 ,5和7求和,转换为二进制求和为101和111的求和,其二进制结果为1100,即十进制数12。对于二进制的加法而言,1+1=0,0+1=1,1+0=1,0+0=0,通过对比位运算中的异或运算,不难发现,此方法与位运算中的异或运算形式很类似,唯一不同是异或运算缺少了相应位置的进位。如果我们能够表示出进位,那么加法运算就可以转换成异或运算+进位运算。现在我们考虑如何表示出两位加数相应位置的进位,我们知道,只有1+1=10的时候会产生向高位的进位,其余三种情况进位都为0,那么该形式我们就可以用逻辑运算“与”来表示,为了表示出向高位进位的动作,我们需要将与出来的结果进行向左移位。简而言之,我们的转换思路是:num1+num2=nunm1^num2+(num1&num2)<<1。

#include<stdio.h> 
#include<stdlib.h> 
int add(int num1,int num2); 
void main()
{
	printf("%d",add(200,300)); 
	system("pause"); 
} 
int add(int num1,int num2)
{ 
	if(0==num2) return num1;//若进位为0,运算结束 
	int temp=num1^num2; 
	int carry=(num1&num2)<<1; 
	return add(temp,carry);//若存在不为0的进位,则重复运算 
} 
//转换为非递归后的算法 
int add2(int num1,int num2)
{
	int temp=0; int carry=0; 
	while(num2!=0)
	{ 
		temp=num1^num2;
		carry=(num1&num2)<<1; 
		num1=temp; 
		num2=carry; 
	} 
	return num1; 
}

      2、如何只用逻辑运算实现减法运算

      将减法转换为加法,实现方法与加法相同,如7-5=7+(-5)。

      3、如何只用逻辑运算实现乘法运算

      在开始本问题之前,我们先熟悉一些有关位运算的知识

      (1)常用的等式:-n=~(n-1)=~n+1。

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

      (3)去掉整数n的二进制中的最后一个1:n&(n-1)。


      我们还是先从一个例子开始分析,1011*1010,因为二进制运算的特殊性,可以将该乘法运算表达式拆分为两个运算,1011*1000和1011*0010的和,从而转换为左移运算,即乘法可以转换为移位和加法运算。最后一个1可以通过n&~(n-1)求得,可通过n&(n-1)去掉,为了高效地得到左移的位数,可以添加一个map容器,算法如下所示:

int multiply(int a ,int b)
{ 
	int sum = 0; 
	map<int, int> m_map; 
	for(int i = 0; i < 32; i++) m_map.insert( pair<int,int>(1 << i, i) );//将int类型的32位状态加入map容器 
	while(b != 0)
	{ 
		int last_bit = m_map[b&~(b-1)];//取最后一个1的下标 
		sum += (a << last_bit);//完全只用逻辑运算的话,该句可以调用加法函数实现 
		b &= b-1; 
	} 
	if(a > 0 && b < 0 || a < 0 && b > 0) sum = -sum; 
	return sum; 
}

      4、如何只用逻辑运算实现除法运算

      (1)一般除法可以采用减法操作或移位操作实现。

      减法操作就是循环用被除数减去除数,每减一次值加1,直到被除数小于除数为止。程序如下:

int div(int a,int b )
{ 
	int result=0; 
	if(b==0)
	{ 
		printf("error!"); 
	
		return; 
	} 
	while(a>=b)
	{ 
		result++; a-=b; 
	} 
	return result; 
} 

(2)采用移位操作实现,位操作的效率一般都比较高效。

int div2( int a, int b)
{ 
	int left_num = a; 
	int result = 0; 
	while(left_num>=b)
	{ 
		int mul=1;//乘数因子 
		while(b*mul<=(left_num>>1)) mul = mul << 1; 
		result+=mul; 
		left_num-=b*mul; 
	} 
	return result; 
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值