參考鏈接: 交換兩個字符串,而無需在Java中使用第三個用戶定義的變量
前言:好久沒有寫博客,最近一年感覺真是好忙,各種做不完的工作。相信很多上班族都會有這種感覺。最近對NFC進行寫卡操作,需要計算一個校驗位。一般情況下,校驗位多數是由前幾個字節進行異或運算所得。?
??
現在我就先說一下我使用的場景:?
把一個16字節的數據寫到CPU卡(如交通卡)里面,最后一字節是校驗碼---前十五字節異或。?
我開始從網上找了一些別人寫的算法發現計算后結果不對,或者就是寫的太復雜了,于是自己就寫了一個,感覺也比較簡單,現在分享給大家,希望一起交流一下。?
第一節:什么是異或運算(主要摘自百度百科,熟悉的童靴可以跳過)?
定義:?
?
?
?異或,英文為exclusive OR,或縮寫成xor
?
?
?異或(xor)是一個數學運算符。它應用于邏輯運算。異或的數學符號為“⊕”,計算機符號為“xor”。其運算法則為:
?
?
?a⊕b = (?a ∧ b) ∨ (a ∧?b)
?
?
?如果a、b兩個值不相同,則異或結果為1。如果a、b兩個值相同,異或結果為0。
?
?
?異或也叫半加運算,其運算法則相當于不帶進位的二進制加法:二進制下用1表示真,0表示假,則異或的運算法則為:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同為0,異為1),這些法則與加法是相同的,只是不帶進位。
?
?
?異或略稱為XOR、EOR、EX-OR
?
?
?程序中有三種演算子:XOR、xor、⊕。
?
?
?使用方法如下
?
?
?z = x ⊕ y
?
?
?z = x xor y
?
運算規則:?
?
?
?
?1. a ⊕ a = 0
?
?
?2. a ⊕ b = b ⊕ a
?
?
?3. a ⊕b ⊕ c = a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ c;
?
?
?4. d = a ⊕ b ⊕ c 可以推出 a = d ⊕ b ⊕ c.
?
?
?5. a ⊕ b ⊕ a = b.
?
?
?6.若x是二進制數0101,y是二進制數1011
?
?
?則x⊕y=1110
?
?
?只有在兩個比較的位不同時其結果是1,否則結果為0
?
?
?即“兩個輸入相同時為0,不同則為1”!
?
?
??
?
邏輯:?
?
?
?
?邏輯表達式:F=AB’⊕A’B((AB’⊕A’B)’=AB⊙A’B’,⊙為“同或”運算)
?
?
?異或邏輯的真值表如圖1所
?
?
? 示,其邏輯符號如圖2所示。異或邏輯的關系是:當AB不同時,輸出P=1;當AB相同時,輸出P=0。“⊕”是異或運算符號,異或邏輯也是與或非邏輯的組合,其邏輯表達式為:
?
?
?P=A⊕B
?
?
?由圖1可知,異或運算的規則是
?
?
?0⊕0=0,0⊕1=1
?
?
?1⊕0=1,1⊕1=0
?
?
?口訣:相同取0,相異取1
??
?
?
?事實上,XOR 在英文里面的定義為either one (is one), but not both, 也即只有一個為真(1)時,取真(1)。
?
作用:?
?
?
?
?在計算機中普遍運用,異或(xor)的邏輯符號一般用xor,也有用⊕的:
?
?
?真⊕假=真
?
?
?假⊕真=真
?
?
?假⊕假=假
?
?
?真⊕真=假
?
?
?或者為:
?
?
?True ⊕ False = True
?
?
?False ⊕ True = True
?
?
?False ⊕ False = False
?
?
?True ⊕ True = False
?
?
?部分計算機語言用1表示真,用0表示假,所以兩個字節按位異或如下
?
? ?
? ??
? ? ?00000000
? ? ??
? ??
? ? ?xor
? ? ??
? ??
? ? ?00000000
? ? ??
? ??
? ? ?----------------------------------
? ? ? ??
? ??
? ? ?00000000
? ? ??
?
?============我是分界線1============
?
?
?下面是兩個二進制數值進行異或計算:
?
? ?
? ??
? ? ?11111111
? ? ??
? ??
? ? ?xor
? ? ??
? ??
? ? ?00000000
? ? ??
? ??
? ? ?----------------------------
? ? ? ??
? ??
? ? ?11111111
? ? ??
?
?============我是分界線2============
?
?
?現實中用的都是十進制的數值,那么我們來看一看兩個十進制數值是怎么進行異或計算:
?
?
?5 ⊕ 2 = ?
?
?
?1.進行異或計算前會把數值都轉換為二進制的:
?
?
?5和2轉為二進制分別為:0101 、0010
?
? ?
? ??
? ? ?0101
? ? ??
? ??
? ? ?xor
? ? ??
? ??
? ? ?0010
? ? ??
? ??
? ? ?----------------------------
? ? ? ??
? ??
? ? ?0111
? ? ??
?
?2.再把結果 0111 轉換為十進制的:7
?
?
?3.所以 5 ⊕ 2 = 7
?
巧用:?
?
?
?
?與其它語言不同,C語言和C++語言的異或不用xor,而是用“^”,鍵入方式為Shift+6。(而其它語言的“^”一般表示乘方)
?
?
?若需要交換兩個變量的值,除了通常使用的借用中間變量進行交換外,還可以利用異或,僅使用兩個變量進行交換,如:
?
?
??
? ?
? ? ? ?
? ? ? ?1
? ? ? ?
? ? ? ?
? ? ? ?2
? ? ? ?
? ? ? ?
? ? ? ?3
? ? ? ??
? ? ? ?
? ? ? ??
? ? ? ? a=a^b;
? ? ? ??
? ? ? ??
? ? ? ? b=b^a;
? ? ? ??
? ? ? ??
? ? ? ? a=a^b;
? ? ? ??
? ? ? ??
??
?
?
?詳解:
?
?
??
? ?
? ? ? ?
? ? ? ?1
? ? ? ?
? ? ? ?
? ? ? ?2
? ? ? ?
? ? ? ?
? ? ? ?3
? ? ? ??
? ? ? ?
? ? ? ??
? ? ? ? a1=a^b
? ? ? ??
? ? ? ??
? ? ? ? b=a1^b
? ? ? ??
? ? ? ??
? ? ? ? a=a1^b=a1^(a1^b)=a1^a1^b=b
? ? ? ??
? ? ? ??
??
?
?
?注意:
?
?
??
? ?
? ? ? ?
? ? ? ?1
? ? ? ??
? ? ? ?
? ? ? ??
? ? ? ? a=a^b^(b=a);//此類形式是不正確的UB行為,在不同編譯器中會有不同的結果,切勿使用
? ? ? ??
? ? ? ??
??
?
?
?這樣就完成了a與b的交換。
?
?
?綜上:同一變量與另一變量和其異或值異或等于自身。
?
?
?用例:可使用于加密算法某一環節或更多環節,使算法更復雜,不易被破解,安全性更高。[1]?
?
第二節:用java語言實現:?
?
??
?
private static String xor(String strHex_X,String strHex_Y){?
? ? ? ? ? ? //將x、y轉成二進制形式?
? ? ? ? ? ? String anotherBinary=Integer.toBinaryString(Integer.valueOf(strHex_X,16));?
? ? ? ? ? ? String thisBinary=Integer.toBinaryString(Integer.valueOf(strHex_Y,16));?
? ? ? ? ? ? String result = "";?
? ? ? ? ? ? //判斷是否為8位二進制,否則左補零?
? ? ? ? ? ? if(anotherBinary.length() != 8){?
? ? ? ? ? ? for (int i = anotherBinary.length(); i <8; i++) {?
? ? ? ? ? ? ? ? ? ? anotherBinary = "0"+anotherBinary;?
? ? ? ? ? ? ? ? }?
? ? ? ? ? ? }?
? ? ? ? ? ? if(thisBinary.length() != 8){?
? ? ? ? ? ? for (int i = thisBinary.length(); i <8; i++) {?
? ? ? ? ? ? ? ? ? ? thisBinary = "0"+thisBinary;?
? ? ? ? ? ? ? ? }?
? ? ? ? ? ? }?
? ? ? ? ? ? //異或運算?
? ? ? ? ? ? for(int i=0;i<anotherBinary.length();i++){?
? ? ? ? ? ? //如果相同位置數相同,則補0,否則補1?
? ? ? ? ? ? ? ? ? ? if(thisBinary.charAt(i)==anotherBinary.charAt(i))?
? ? ? ? ? ? ? ? ? ? ? ? result+="0";?
? ? ? ? ? ? ? ? ? ? else{?
? ? ? ? ? ? ? ? ? ? ? ? result+="1";?
? ? ? ? ? ? ? ? ? ? }?
? ? ? ? ? ? ? ? }
? ? ? ? ? ? Log.e("code",result);
? ? ? ? ? ? return Integer.toHexString(Integer.parseInt(result, 2));?
? ? ? ? }?
注意:以上方法是針對一個十六進制字符串一字節之間的異或運算,如對十五字節的十六進制字符串異或運算:1312f70f900168d900007df57b4884?
先進行拆分:13 12 f7 0f 90 01 68 d9 00 00 7d f5 7b 48 84?
13 xor 12-->1?
1 xor f7-->f6?
f6 xor 0f-->f9?
....?
62 xor 84-->e6?
即,得到的一字節校驗碼為:e6?
補充,給一些朋友增加了一個簡單的調用方法,僅供參考:?
?
public String checkcode_0007(String para){
? ? ? ? ?String[] dateArr = new String[15];
? ? ? ? ?try {
? ? ? ? ? ? ?dateArr[0] = para.substring(0, 2);
? ? ? ? ? ? ?dateArr[1] = para.substring(2, 4);
? ? ? ? ? ? ?dateArr[2] = para.substring(4, 6);
? ? ? ? ? ? ?dateArr[3] = para.substring(6, 8);
? ? ? ? ? ? ?dateArr[4] = para.substring(8, 10);
? ? ? ? ? ? ?dateArr[5] = para.substring(10, 12);
? ? ? ? ? ? ?dateArr[6] = para.substring(12, 14);
? ? ? ? ? ? ?dateArr[7] = para.substring(14, 16);
? ? ? ? ? ? ?dateArr[8] = para.substring(16, 18);
? ? ? ? ? ? ?dateArr[9] = para.substring(18, 20);
? ? ? ? ? ? ?dateArr[10] = para.substring(20, 22);
? ? ? ? ? ? ?dateArr[11] = para.substring(22, 24);
? ? ? ? ? ? ?dateArr[12] = para.substring(24, 26);
? ? ? ? ? ? ?dateArr[13] = para.substring(26, 28);
? ? ? ? ? ? ?dateArr[14] = para.substring(28, 30);
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? // TODO: handle exception
? ? ? ? }
? ? ? ? String code = "";
? ? ? ? for (int i = 0; i < dateArr.length-1; i++) {
? ? ? ? ? ? if(i == 0){
? ? ? ? ? ? ? ? code = xorString(dateArr[i], dateArr[i+1]);
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? code = xorString(code, dateArr[i]);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return code;
}然后再主函數或者其他方法里面調用:?
?
?
String code = checkcode_0007("1312f70f900168d900007df57b4884");code就是獲取的校驗碼了。