簡體   English   中英

為什么(a | b)相當於 - (a&b)+ b?

[英]Why is (a | b ) equivalent to a - (a & b) + b?

我正在尋找一種方法來使用Oracle數據庫進行BITOR()並且遇到了一個建議,只需使用BITAND()代替BITOR(a,b)替換為+ b - BITAND(a,b)。

我用手測試了幾次並驗證它似乎適用於我能想到的所有二進制數,但我無法想出為什么這是正確的快速數學證明。
有人可以開導我嗎?

A和B是在A和B中都打開的位組.A - (A和B)為您留下所有那些僅在A中打開的位。將B添加到該位,並獲得所有位在A中或在B中的那些

簡單地添加A和B將不起作用,因為攜帶兩個都有1位。 通過首先去除A和B共同的位,我們知道(A-(A和B))將沒有與B共同的位,因此保證將它們加在一起不會產生進位。

想象一下,你有兩個二進制數: ab 並且假設這些數字在同一位中同時沒有1,即如果a在某個位中有1,則b在相應位中始終為0。 而在其它方向上,如果b在一些比特具有1,則a總是在該位為0。 例如

a = 00100011
b = 11000100

這將是滿足上述條件的ab的示例。 在這種情況下很容易看出a | b a | ba + b完全相同。

a | b = 11100111
a + b = 11100111

現在讓我們取兩個違反我們條件的數字,即兩個數字在某個公共位中至少有一個1

a = 00100111
b = 11000100

a | b a | b在這種情況下是否與a + b相同? 沒有

a | b = 11100111
a + b = 11101011

他們為什么不同? 它們是不同的,因為當我們+在兩個數字中都有1的位時,我們產生所謂的進位 :結果位為0,並且1被傳送到左邊的下一位: 1 + 1 = 10 操作| 沒有攜帶,所以1 | 1 1 | 1再次只是1。

這意味着a | b的區別 當且僅當數字在公共位中具有至少一個1時,才出現a | ba + b 當我們將兩個數字與1個公共位相加時,這些公共位被“加”兩次並產生一個進位,這破壞了a | b之間的相似性a | b a | ba + b

現在看看a & b a & b計算什么? a & b產生的數字在ab都有1的所有位中都有1.在我們的最新例子中

a =     00100111
b =     11000100
a & b = 00000100

如上所述,這些正是使a + ba | b不同的位 a | b a & b的1表示將發生進位的所有位置。

現在,當我們做a - (a & b)我們有效地從a和僅這樣的位中刪除 (減去)所有“有問題”的位

a - (a & b) = 00100011

數字a - (a & b)b沒有共同的1位,這意味着如果我們添加a - (a & b)b我們將不會遇到進位,並且,如果你考慮它,我們應該最后得到的結果就像我們剛剛做a | b a | b

a - (a & b) + b = 11100111

A和B = C,其中在C中設置的任何位是在A和B中設置的位。
AC = D或BC = E將這些公共位設置為0.沒有攜帶效應,因為1-1 = 0。
D + B或E + A類似於A + B,不同之處在於因為我們先前減去了A和B,所以由於清除了D或E中所有常用的位,所以不會有進位。

最終結果是AA&B + B或BA&B + A等同於A | B.

這是一個真值表,如果它仍然令人困惑:

A | B | OR   A | B | &    A | B | -    A | B | + 
---+---+---- ---+---+---  ---+---+---  ---+---+---
 0 | 0 | 0    0 | 0 | 0    0 | 0 | 0    0 | 0 | 0  
 0 | 1 | 1    0 | 1 | 0    0 | 1 | 0-1  0 | 1 | 1
 1 | 0 | 1    1 | 0 | 0    1 | 0 | 1    1 | 0 | 1  
 1 | 1 | 1    1 | 1 | 1    1 | 1 | 0    1 | 1 | 1+1

注意+和 - 操作中的進位行,我們避免那些,因為A-(A和B)設置的情況都是A中的位,B中的A是1到0,然后從B中添加它們也帶來了其他情況在A或B中是1,但兩者都不是0,所以OR真值表和A-(A&B)+ B真值表是相同的。

另一種觀察它的方法是看到A + B幾乎像A | B,除了底行的進位。 A&B隔離了我們的底行,AA&B將那些隔離的那些移動到+表中的兩行,並且(AA和B)+ B變得等同於A | B.

雖然你可以將它轉交給A + B-(A和B),但我擔心可能出現溢出,但這似乎是不合理的:

#include <stdio.h>
int main(){ unsigned int a=0xC0000000, b=0xA0000000;
printf("%x %x %x %x\n",a,   b,       a|b,       a&b);
printf("%x %x %x %x\n",a+b, a-(a&b), a-(a&b)+b, a+b-(a&b)); }

c0000000 a0000000 e0000000 80000000
60000000 40000000 e0000000 e0000000

編輯 :所以我在得到答案之前寫了這個,然后在我的家庭連接上有兩個小時的停機時間,我終於設法發布它,之后才注意到它已經被正確回答了兩次。 就個人而言,我更喜歡使用真值表來計算按位運算,所以我會留下它以防萬一它可以幫助某人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM