我正在寻找在Oracle数据库中执行BITOR()的方法,偶然发现建议使用BITAND()来替代BITOR(),具体操作是将BITOR(a,b)替换为a + b - BITAND(a,b)。
我手动验证了几次,似乎对我能想到的所有二进制数都有效,但我无法快速想出为什么这是正确的数学证明。
能否有人给我讲解一下?
我正在寻找在Oracle数据库中执行BITOR()的方法,偶然发现建议使用BITAND()来替代BITOR(),具体操作是将BITOR(a,b)替换为a + b - BITAND(a,b)。
我手动验证了几次,似乎对我能想到的所有二进制数都有效,但我无法快速想出为什么这是正确的数学证明。
能否有人给我讲解一下?
A & B 是 A 和 B 中都为 1 的位。 A - (A & B) 留下了所有仅在 A 中为 1 的位。将 B 加入其中,您将得到在 A 或 B 中为 1 的所有位。
简单地将 A 和 B 相加不起作用,因为当两个位置都为 1 时会产生进位。通过先移除 A 和 B 共同的位,我们知道 (A-(A&B)) 与 B 没有任何公共位,因此将它们加在一起保证不产生进位。
a&b
的减法正确地恢复了进位的“破坏性”影响。 - AnT stands with Russia假设你有两个二进制数:a
和b
。并且假设这些数字在任何时候都没有相同的位上同时为1,即如果a
的某个位上有1,则相应的位上b
始终为0。反之亦然,如果b
的某个位上有1,则a
在那一位上始终为0。例如:
a = 00100011
b = 11000100
这是满足上述条件的a
和b
的示例。在这种情况下,很容易看出a | b
将完全与a + b
相同。
a | b = 11100111
a + b = 11100111
现在我们考虑两个违反条件的数字,也就是说,这两个数字在某个公共位至少有一个1。
a = 00100111
b = 11000100
在这种情况下,a | b
和a + b
是相同的吗?不是。
a | b = 11100111
a + b = 11101011
为什么它们不同?它们不同是因为当我们将两个数字中都有1的位相加时,会产生所谓的“进位”:结果位为0,1被传递到左侧下一位:1 + 1 = 10
。操作|
没有进位,所以1 | 1
仍然是1。a | b
和a + b
之间的差异仅在于数字至少有一个共同的1位时才会发生。当我们将具有共同1位的两个数字相加时,这些公共位会被"加倍"并产生进位,从而破坏了a | b
和a + b
之间的相似性。a & b
。 a & b
计算什么? a & b
生成在a
和b
都有1的所有位上都有1的数字。在我们最新的例子中。a = 00100111
b = 11000100
a & b = 00000100
正如你在上面看到的,这些位刚好是使得 a + 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 - (a & b) + b = 11100111
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中的两个位都是1的情况设置为0。然后从B中添加回这些值,也带回了另一种情况,即A或B中有一个位是1而不是两个位都是0。因此,OR真值表和A-(A&B)+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
< p > < em >编辑:在没有答案之前,我写了这个问题,然后我的家庭连接出现了2小时的宕机,最终我设法将其发布,之后才注意到已经有两个正确的答案。就我个人而言,我更喜欢参考真值表来计算位运算,因此我会将其保留以帮助某些人。
BITAND()
但没有BITOR()
? - Thanatos