1. 程式人生 > >如何只用邏輯運算實現算術加減乘除運算

如何只用邏輯運算實現算術加減乘除運算

      我們知道,在邏輯代數中,有與、或、非三種基本邏輯運算。通過三種基本邏輯運算之間的組合運算,又可以構造出與非、或非、異或等常用運算。我們在編寫計算機程式碼的時候,通過加減乘除運算子可以很容易地實現該基本運算,但是我們如何使用邏輯運算來實現算術加減乘除基本運算呢?


      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; 
}