Java中異或的深入講解
前言
異或是一種基于二進(jìn)制的位運(yùn)算,用符號(hào)XOR或者 ^ 表示,其運(yùn)算法則是對(duì)運(yùn)算符兩側(cè)數(shù)的每一個(gè)二進(jìn)制位,同值取0,異值取1。
性質(zhì)
1、交換律
2、結(jié)合律(即(a^b)^c == a^(b^c))
3、對(duì)于任何數(shù)x,都有x^x=0,x^0=x
4、自反性 A XOR B XOR B = A XOR 0 = A
異或運(yùn)算最常見于多項(xiàng)式除法,不過(guò)它最重要的性質(zhì)還是自反性:A XOR B XOR B = A,即對(duì)給定的數(shù)A,用同樣的運(yùn)算因子(B)作兩次異或運(yùn)算后仍得到A本身。這是一個(gè)神奇的性質(zhì),利用這個(gè)性質(zhì),可以獲得許多有趣的應(yīng)用。 例如,所有的程序教科書都會(huì)向初學(xué)者指出,要交換兩個(gè)變量的值,必須要引入一個(gè)中間變量。但如果使用異或,就可以節(jié)約一個(gè)變量的存儲(chǔ)空間: 設(shè)有A,B兩個(gè)變量,存儲(chǔ)的值分別為a,b,則以下三行表達(dá)式將互換他們的值 表達(dá)式 (值) :
A=A XOR B (a XOR b)
B=B XOR A (b XOR a XOR b = a)
A=A XOR B (a XOR b XOR a = b)
例:
int a = 10, b = 5 a = a ^ b; b = a ^ b; a = a ^ b;
類似地,該運(yùn)算還可以應(yīng)用在加密,數(shù)據(jù)傳輸,校驗(yàn)等等許多領(lǐng)域。
應(yīng)用舉例:1-1000放在含有1001個(gè)元素的數(shù)組中,只有唯一的一個(gè)元素值重復(fù),其它均只出現(xiàn)一次。每個(gè)數(shù)組元素只能訪問(wèn)一次,設(shè)計(jì)一個(gè)算法,將它找出來(lái);不用輔助存儲(chǔ)空間,能否設(shè)計(jì)一個(gè)算法實(shí)現(xiàn)?
解法一、顯然已經(jīng)有人提出了一個(gè)比較精彩的解法,將所有數(shù)加起來(lái),減去1+2+...+1000的和。這個(gè)算法已經(jīng)足夠完美了,相信出題者的標(biāo)準(zhǔn)答案也就是這個(gè)算法,唯一的問(wèn)題是,如果數(shù)列過(guò)大,則可能會(huì)導(dǎo)致溢出。
解法二、異或就沒(méi)有這個(gè)問(wèn)題,并且性能更好。將所有的數(shù)全部異或,得到的結(jié)果與1^2^3^...^1000的結(jié)果進(jìn)行異或,得到的結(jié)果就是重復(fù)數(shù)。
但是這個(gè)算法雖然很簡(jiǎn)單,但證明起來(lái)并不是一件容易的事情。這與異或運(yùn)算的幾個(gè)特性有關(guān)系。首先是異或運(yùn)算滿足交換律、結(jié)合律。
所以,1^2^...^n^...^n^...^1000,無(wú)論這兩個(gè)n出現(xiàn)在什么位置,都可以轉(zhuǎn)換成為1^2^...^1000^(n^n)的形式。
其次,對(duì)于任何數(shù)x,都有x^x=0,x^0=x。
所以1^2^...^n^...^n^...^1000 = 1^2^...^1000^(n^n)= 1^2^...^1000^0 = 1^2^...^1000(即序列中除了n的所有數(shù)的異或)。
令,1^2^...^1000(序列中不包含n)的結(jié)果為T
則1^2^...^1000(序列中包含n)的結(jié)果就是T^n。
T^(T^n)=n。
所以,將所有的數(shù)全部異或,得到的結(jié)果與1^2^3^...^1000的結(jié)果進(jìn)行異或,得到的結(jié)果就是重復(fù)數(shù)。
當(dāng)然有人會(huì)說(shuō),1+2+...+1000的結(jié)果有高斯定律可以快速計(jì)算,但實(shí)際上1^2^...^1000的結(jié)果也是有規(guī)律的,算法比高斯定律還該簡(jiǎn)單的多。
google面試題的變形:一個(gè)數(shù)組存放若干整數(shù),一個(gè)數(shù)出現(xiàn)奇數(shù)次,其余數(shù)均出現(xiàn)偶數(shù)次,找出這個(gè)出現(xiàn)奇數(shù)次的數(shù)?
public void fun() {
int a[] = { 22, 38,38, 22,22, 4, 4, 11, 11 };
int temp = 0;
for (int i = 0; i < a.length; i++) {
temp ^= a[i];
}
System.out.println(temp);
}
解法有很多,但是最好的和上面一樣,就是把所有數(shù)異或,最后結(jié)果就是要找的,原理同上!!
************************************分割線*******************************************
這樣可以實(shí)現(xiàn)不引人第三個(gè)變量實(shí)現(xiàn)交換,但是進(jìn)行的計(jì)算相對(duì)第三個(gè)變量多,所以效率會(huì)低一些。
關(guān)于其他的方法還有:int a=5,b=10;
a=a+b; //a=15,b=10
b=a-b; //a=15,b=5
a=a-b; //a=10,b=5
但是這樣做有一個(gè)缺陷,假設(shè)它運(yùn)行在vc6環(huán)境中,那么int的大小是4 Bytes,所以int變量所存放的最大值是2^31-1即2147483647,如果我們令a的值為2147483000,b的值為1000000000,那么a和b相加就越界了。
事實(shí)上,從實(shí)際的運(yùn)行統(tǒng)計(jì)上看,我們發(fā)現(xiàn)要交換的兩個(gè)變量,是同號(hào)的概率很大,而且,他們之間相減,越界的情況也很少,因此我們可以把上面的加減法互換,這樣使得程序出錯(cuò)的概率減少:
int a=5,b=10;
a -= b; //a=-5,b=10
b += a; //b=5,a=-5
a = b - a; //a=10,b=5
通過(guò)以上運(yùn)算,a和b中的值就進(jìn)行了交換。表面上看起來(lái)很簡(jiǎn)單,但是不容易想到,尤其是在習(xí)慣引入第三變量的算法之后。
它的原理是:把a(bǔ)、b看做數(shù)軸上的點(diǎn),圍繞兩點(diǎn)間的距離來(lái)進(jìn)行計(jì)算。
具體過(guò)程:第一句“a-=b”求出ab兩點(diǎn)的距離,并且將其保存在a中;第二句“b+=a”求出a到原點(diǎn)的距離(b到原點(diǎn)的距離與ab兩點(diǎn)距離之差),并且將其保存在b中;第三句“a+=b”求出b到原點(diǎn)的距離(a到原點(diǎn)距離與ab兩點(diǎn)距離之和),并且將其保存在a中。完成交換。
下面順便介紹交換兩個(gè)數(shù) 的三種方法:

總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
- java異或加密算法
- Java中位運(yùn)算(移位、位與、或、異或、非) 的簡(jiǎn)單實(shí)例
- Java中使用異或運(yùn)算符實(shí)現(xiàn)加密字符串
- java使用異或?qū)崿F(xiàn)變量互換和異或加密解密示例
- Java編程實(shí)現(xiàn)對(duì)十六進(jìn)制字符串異或運(yùn)算代碼示例
- Java中使用異或語(yǔ)句實(shí)現(xiàn)兩個(gè)變量的互換
- Java使用異或運(yùn)算實(shí)現(xiàn)簡(jiǎn)單的加密解密算法實(shí)例代碼
- java中的異或問(wèn)題代碼解析
- Java異或技操作給任意的文件加密原理及使用詳解
- java實(shí)現(xiàn)兩個(gè)文件的異或運(yùn)算
相關(guān)文章
Java微信公眾平臺(tái)開發(fā)(15) 微信JSSDK的使用
這篇文章主要為大家詳細(xì)介紹了Java微信公眾平臺(tái)開發(fā)第十五步,微信JSSDK的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
elasticsearch的靈魂唯一master選舉機(jī)制原理分析
這篇文章主要為大家介紹了elasticsearch的靈魂唯一master選舉機(jī)制原理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04
Java中的引用和動(dòng)態(tài)代理的實(shí)現(xiàn)詳解
這篇文章主要介紹了Java中的引用和動(dòng)態(tài)代理的實(shí)現(xiàn)詳解,涉及Java中的引用類型,JVMGC的可達(dá)性分析,代理模式等相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11
解決Eclipse/STS中出現(xiàn)Resource is out of sync with the file system
今天小編就為大家分享一篇關(guān)于解決Eclipse/STS中出現(xiàn)Resource is out of sync with the file system的異常問(wèn)題,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12
java使用Nagao算法實(shí)現(xiàn)新詞發(fā)現(xiàn)、熱門詞的挖掘
這篇文章主要介紹了java使用Nagao算法實(shí)現(xiàn)新詞發(fā)現(xiàn)、熱門詞的挖掘的思路和詳細(xì)代碼,需要的朋友可以參考下2015-07-07
實(shí)例分析Java中public static void main(String args[])是什么意思
這篇文章主要介紹了實(shí)例分析Java中public static void main(String args[])的意義,詳細(xì)分析了Java主函數(shù)main關(guān)鍵字聲明的具體含義和用法,需要的朋友可以參考下2015-12-12
Spring boot 路徑映射的實(shí)現(xiàn)
這篇文章主要介紹了spring boot 路徑映射的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
Java實(shí)現(xiàn)Redis的集合(set)命令操作
這篇文章主要介紹了Java實(shí)現(xiàn)Redis的集合(set)命令操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07

