Java利用位運算實現(xiàn)加減運算詳解
前言
本文主要介紹如何使用位運算來實現(xiàn)加減功能,也就是在整個運算過程中不能出現(xiàn)加減符號。
加減乘除運算在計算機中,實際上都是用位運算實現(xiàn)的,今天就用位運算來模擬下加法和減法的運算功能。
思路分析
先分析如何用位運算實現(xiàn)加法運算。
示例
假設(shè)a=23,b=36,使用位運算實現(xiàn)加法得到結(jié)果59。
首先來看下23、36、59的二進制信息。

從上面的圖中可以看到,兩個數(shù)相加的結(jié)果與兩個數(shù)異或的結(jié)果很相似,只不過在圖中的2位置相加的時候,產(chǎn)生了進位,而異或是沒有進位的,如果能拿到進位信息,把兩個數(shù)異或的結(jié)果和進位信息的結(jié)果相加就能得到最終結(jié)果了,那么如果能拿到進位信息呢?
位運算進位
上圖中,59的二進制信息可以分為兩部分,0110011 和 0001000,再結(jié)合23、36的二進制信息來看,0110011為23和36的異或結(jié)果,而23和36相與的結(jié)果跟0001000很相似,只不過0001000中的1比相與結(jié)果往前移了一位。
于是,我們可以得出,兩個數(shù)的二進制進位信息為兩個數(shù)的相與在左移一位。
初步結(jié)果
經(jīng)過上面的分析,我們可以得到了一個初步的運算結(jié)果,即兩個數(shù)相加等于兩個數(shù)異或加上兩個數(shù)的相與左移1位,也就是a + b = (a ^ b) + ((a & b) << 1)。
先用23和36來驗證下。

經(jīng)過驗證可以看到,剛才得出的結(jié)論是正確的。
但是,我們要做到在整個運算過程中不能出現(xiàn)加號,接下來要想辦法把這個加號給去掉。
去除加號
還是以23和36為例,經(jīng)過上面的運算我們把運算的位運算結(jié)果給化簡下。
23 + 36 = (23 ^ 36) + ((23 & 36) << 1) = 51 + 8
也就是把23和36的相加運算轉(zhuǎn)化為了51和8的相加運算,接下來繼續(xù)分析51和8的相加運算,也是通過異或和相與進行操作。
51 + 8 = (51 ^ 8) + ((51 & 8) << 1) = 59 + 0
嗯?可以發(fā)現(xiàn)我們已經(jīng)得出59了,而且還加了個0,加了個0不就相當于加了個寂寞嘛,可以直接省略啊。
由此,我們又可以得出一個結(jié)論,兩個數(shù)的二進制進位信息為兩個數(shù)的相與在左移一位,不停地循環(huán)這個過程,直到有一個數(shù)變?yōu)?,就能得到結(jié)果。
整體思路
現(xiàn)在來總結(jié)下整體的計算過程:
- 把兩個數(shù)相加,拆分成兩步,兩個數(shù)異或加上兩個數(shù)相與左移1位。
- 判斷相與左移的結(jié)果是否為0。
- 如果相與左移為0,兩個數(shù)異或的結(jié)果即為相加的結(jié)果。
- 如果相與左移結(jié)果不為0,把得到的新結(jié)果,重復執(zhí)行第1~3步操作。
加法代碼實現(xiàn)
經(jīng)過上面的分析,來看下代碼實現(xiàn)。
public class Code19_Add {
public static int add(int a, int b) {
int sum = 0;
while (b != 0) {
sum = a ^ b;
b = (a & b) << 1;
a = sum;
}
return sum;
}
public static void main(String[] args) {
int sum = add(23, 36);
System.out.println(sum);
}
}運行程序,輸出結(jié)果為59。
減法實現(xiàn)
減法分析
還是以23和36為例,如果要計算 36 - 23,該怎么辦?
36 - 23 不就相當于36 + (-23),可以理解為加上一個負數(shù),這就可以了嗎?不不不,要求的是不能出現(xiàn)加減符號,-23里面是有減法這個符號的。
還記得前面我們分析的負數(shù)可以怎么表示嗎?對了,負數(shù)是對一個數(shù)的取反再加1。嗯?又出現(xiàn)加號了,不過加法我們不是已經(jīng)實現(xiàn)了嗎?直接拿來用就好了。
減法代碼實現(xiàn)
有了加法操作,減法就很簡單了,來看下代碼。
public class Code20_Sub {
public static int add(int a, int b) {
int sum = 0;
while (b != 0) {
sum = a ^ b;
b = (a & b) << 1;
a = sum;
}
return sum;
}
public static int sub(int a, int b) {
return add(a, add(~b, 1));
}
public static void main(String[] args) {
int sum = sub(36, 23);
System.out.println(sum);
}
}運行一下輸出結(jié)果為13。
嗯,Perfect!
總結(jié)
本文主要介紹如何使用位運算來實現(xiàn)加減功能,至此功能都已經(jīng)實現(xiàn)了。
那么問題來了,我們實現(xiàn)的加減運算與Java本身的加減相比,誰的效率更高呢?當然是Java中的更高了,因為我們是用Java實現(xiàn)的,代碼運行后,要經(jīng)過層層的翻譯才能到達底層,所以效率肯定是有損失的。
當然我們的目的是熟悉位運算的操作,這個才是最重要的。
到此這篇關(guān)于Java利用位運算實現(xiàn)加減運算詳解的文章就介紹到這了,更多相關(guān)Java位運算實現(xiàn)加減運算內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IDEA 中使用 ECJ 編譯出現(xiàn) java.lang.IllegalArgumentException的錯誤問題
這篇文章主要介紹了IDEA 中使用 ECJ 編譯出現(xiàn) java.lang.IllegalArgumentException問題 ,本文內(nèi)容簡短給大家介紹的好,需要的朋友可以參考下2020-05-05
Java使用FilenameFilter查找出目錄下指定后綴的文件示例
這篇文章主要介紹了Java使用FilenameFilter查找出目錄下指定后綴的文件,結(jié)合實例形式分析了java基于FilenameFilter類的文件遍歷、查找相關(guān)操作技巧,需要的朋友可以參考下2019-10-10
SpringBoot中FailureAnalyzer的使用詳解
這篇文章主要介紹了SpringBoot中FailureAnalyzer的使用詳解,FailureAnalyzer攔截啟動時異常,將異常轉(zhuǎn)換成更加易讀的信息并包裝成org.springframework.boot.diagnostics.FailureAnalysis對象,監(jiān)控應用啟動過程,需要的朋友可以參考下2023-12-12
intellij idea隱藏.iml和.idea等自動生成文件的問題
這篇文章主要介紹了intellij idea隱藏.iml和.idea等自動生成文件的問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09

