如何只用邏輯運算實現算術加減乘除運算
阿新 • • 發佈:2019-02-04
我們知道,在邏輯代數中,有與、或、非三種基本邏輯運算。通過三種基本邏輯運算之間的組合運算,又可以構造出與非、或非、異或等常用運算。我們在編寫計算機程式碼的時候,通過加減乘除運算子可以很容易地實現該基本運算,但是我們如何使用邏輯運算來實現算術加減乘除基本運算呢?
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。
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容器,演算法如下所示:
4、如何只用邏輯運算實現除法運算
(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; }