What's the insight behind A XOR B in bitwise operation? - bit-manipulation

What I know for A XOR B operation is that the output is 1 if A != B, and 0 if A == B. However, I have no insight about this operation when A and B are not binary.
For example, if A = 1, B = 3, then A XOR B = 2; also, if A = 2, B = 3, then A XOR B = 1. Is there any pattern to the XOR operation for non-binary values?
I have a good understanding of boolean mathematics, so I already understand how XOR works. What I am asking is that how do you, for example, predict the outcome of A XOR B without going through the manual calculation, if A and B are not binaries? Let's pretend that 2 XOR 3 = 1 is not just a mathematical artifact.
Thanks!

Just look at the binary representations of the numbers, and perform the following rules on each bit:
0 XOR 0 = 0
0 XOR 1 = 1
1 XOR 0 = 1
1 XOR 1 = 0
So, 1 XOR 3 is:
1 = 001
3 = 011
XOR = 010 = 2
To convert a (decimal) number to binary, repeatedly divide by two until you get to 0, and then the remainders in reverse order is the binary number:
To convert it back, repeatedly subtract it by the largest power of two that's no bigger than it until you get to 0, having each position in the binary number corresponding to the powers you subtracted by set to 1 (the left-most position corresponds to the 0-th power):
(Images reference)

xor on integers and other data is simply xor of the individual bits:
A: 0|0|0|1 = 1
B: 0|0|1|1 = 3
=======
A^B: 0|0|1|0 = 2
^-- Each column is a single bit xor

When you use bit operations on numbers that are more than one bit, it simply performs the operation on each corresponding bit in the inputs, and that becomes the corresponding bit in the output. So:
A = 1 = 00000001
B = 3 = 00000011
--------
result= 00000010 = 2
A = 2 = 00000010
B = 3 = 00000011
--------
result= 00000001 = 1
The result has a 0 bit wherever the input bits were the same, a 1 bit wherever they were different.
You use the same method when performing AND and OR on integers.

Related

Using AND bitwise operator between a number, and its negative counterpart

I stumbled upon this simple line of code, and I cannot figure out what it does. I understand what it does in separate parts, but I don't really understand it as a whole.
// We have an integer(32 bit signed) called i
// The following code snippet is inside a for loop declaration
// in place of a simple incrementor like i++
// for(;;HERE){}
i += (i&(-i))
If I understand correctly it uses the AND binary operator between i and negative i and then adds that number to i. I first thought that this would be an optimized way of calculating the absolute value of an integer, however as I come to know, c++ does not store negative integers simply by flipping a bit, but please correct me if I'm wrong.
Assuming two's complement representation, and assuming i is not INT_MIN, the expression i & -i results in the value of the lowest bit set in i.
If we look at the value of this expression for various values of i:
0 00000000: i&(-i) = 0
1 00000001: i&(-i) = 1
2 00000010: i&(-i) = 2
3 00000011: i&(-i) = 1
4 00000100: i&(-i) = 4
5 00000101: i&(-i) = 1
6 00000110: i&(-i) = 2
7 00000111: i&(-i) = 1
8 00001000: i&(-i) = 8
9 00001001: i&(-i) = 1
10 00001010: i&(-i) = 2
11 00001011: i&(-i) = 1
12 00001100: i&(-i) = 4
13 00001101: i&(-i) = 1
14 00001110: i&(-i) = 2
15 00001111: i&(-i) = 1
16 00010000: i&(-i) = 16
We can see this pattern.
Extrapolating that to i += (i&(-i)), assuming i is positive, it adds the value of the lowest set bit to i. For values that are a power of two, this just doubles the number.
For other values, it rounds the number up by the value of that lowest bit. Repeating this in a loop, you eventually end up with a power of 2. As for what such an increment could be used for, that depends on the context of where this expression was used.

Walkthrough: sum 2 integers using bit manipulation

I am trying to understand the logic behind the following code which sums 2 integers using bit manipulation:
def sum(a, b):
while b != 0:
carry = a & b
a = a ^ b
b = carry << 1
return a
As an example I used: a = 11 and b = 7
11 in binary representation is 1011
7 in binary representation is 0111
Then I walked through the algorithm:
iter #1: a = 1011, b = 0111
carry = 0011 (3 decimal)
a = 1100 (12 decimal)
b = 0110 (6 decimal)
iter #2: a = 1100, b = 0110
carry = 0100 (4 decimal)
a = 1010 (10 decimal)
b = 1000 (8 decimal)
iter #3: a = 1010, b = 1000
carry = 1000 (8 decimal)
a = 00010 (2 decimal)
b = 10000 (16 decimal)
iter #4: a = 00010, b = 10000
carry = 00000 (0 decimal)
a = 10010 (18 decimal)
b = 00000 (0 decimal)
We Done (because b is now 0).
As we can see, in all iterations a+b is always 18 which is the right answer.
However I failed to understand what is actually happens here. The value of a is going down and down with each iteration until suddenly pops to 18 in the last iteration. Also, can we learn anything from the value of the carry during the process?
I would love to understand the intuition behind this.
Thanks to #WJS answer I think I got it.
let's add 11 and 7 as before, but let's do it in the following order:
First, calculate it without the carry.
Second, calculate only the carry.
Then add both parts.
01011
00111
-----
01100 (neglecting carry)
00110 (finding only the carry)
-----
10010 (sum)
Now, to find the first part, how can we get rid of the carry bits? with XOR.
To find the second part, we use AND and then shift it 1 bit left to place it "under" the right bit.
Now all we have to do is sum both parts. The whole point is not using + operator so how can we do that? Recursion!
We assign the first part to a and the second part to b and we repeat this process until b=0 which means we are done.
Perhaps if you take a simpler example it will help.
a = 11
b = 11
a & b == 11 since AND returns 1's where both bits in the same
position are 1. These are the carry bits.
Now get rid of the the carry locations using exclusive or
a = a ^ b == 00
But a `carry` would cause addition to add bits one position to
the left so shift the carry bits left by 1 bit.
b = carry << 1 = 110
now repeat the process
carry = a & b = 0 & 110 == 0 no more carries
b = carry << 1 == 0
done.
11 + 11 = 110 = 3 + 3 = 6
Understanding the roles of (AND) & and (XOR) ^ are key. Applying those to slightly more complex examples should help. But ignore the interim decimal values as they don't help much. Think only about what is happening in binary.
I think this is easy to understand if you look at what happens with individual bits.
First step is calculating carry which only happens in binary when both bits are 1, so a&b calculates that for every bit. Then bitwise addition is happening via XOR (ignoring carry), and XOR works because:
0+0=0 (==0^0)
1+0=1 (==1^0)
1+1=0 (==1^1, generates carry bit which we ignore)
Next step is to shift carry to the left (<<1), move it to b and repeat until carry is empty.

0 minus 0 gives carryout of 1 in adder-subtractor circuit

In this adder-subtractor design with the "M" input as the flag for subtraction, 0 minus 0 seems to provide the incorrect Cout. Let's assume that we're only using one full adder here (ignore A1/B1, A2/B2, A3/B3) for simplicity, and M=1, A0=0, A1=0:
The full adder will get the inputs of:
0 (B0) XOR 1 (M) = 1
0 (A0) = 0
1 (M) = 1
This results in 1+1=0, with Cout = 1 - but Cout should equal 0 for a full adder:
I think inverting the final Cout will provide the correct result, but everywhere I look online for this adder-subtractor circuit has no inverter for the final Cout. Is this circuit supposed to have an inverter at the final Cout to fix this problem?
The carry out equal to 1 is perfectly normal in this case.
When you work with unsigned logic the carry out is used as an overflow flag: assuming you're working with 4-bits operands, the operation:
a = 1000, b = 1001 (Decimal a = 8, b = 9)
1000 +
1001 =
--------
1 0001
produces a carry out of 1'b1 because the result of 8+9 cannot be represented on 4 bits.
On the other hand, when working with signed logic the carry out signal loses its 'overflow' meaning. Let's make an example:
a = 0111, b = 0010 (Decimal a = 7, b = 2)
0111 +
0010 =
--------
0 1001
In this case the result is 1001, that is -7 in two's complement. It's obvious that we had an overflow, since we added two positive numbers and we got a negative one. The carry out, anyway, is equal to 0. As a last case, if we consider:
a = 1111, b = 0001 (Decimal a = -1, b = 1)
1111 +
0001 =
--------
1 0000
we see that even though the result is correct -1+1=0, the carry out is set.
To conclude, if you work in signed logic and you need to understand whether there was an overflow, you need to check the sign of the two operands against the result's one.
Both operands positive (MSB = 0) and result negative (MSB = 1): overflow
Both operands negative (MSB = 1) and result positive (MSB = 0): overflow
Any other case: no overflow

Why is x^0 = x?

I have a very simple question.
Why is a number when XOR'ed with 0 gives the number itself.
Can someone please give the proof using an example.
Lets say I have the number 5
5^0==>
I think the answer should be just the last bit of 5 XOR'ed with 0, but the answer is still 5.
0 is false, and 1 is true.
As per the definition, XOR operation A XOR B is "A or B, but not, A and B". So, since B is false, so the result will be A.
Also, XOR truth table shows that it outputs true whenever the inputs differ:
Input Output
A B XOR Result
0 0 0
0 1 1
1 0 1
1 1 0
As you can see, whatever be the value of A, if it is XORed with 0, the result is the bit itself.
So, as you say:
5 = 101, 0 = 000
When performing XOR operation on the individual bits:
101
000
----
101 = 5.
Hence, the result of X^0 is X itself.
What is there that you did not understand. Please read about XOR
00000101 // = 5
00000000 // = 0
--------
00000101 // = 5
Bit-wise operations operates on set of bits in number - not just on last bit.
So if you perform some bit-wise operation on 32-bit integer, then all 32 bits are affected. So integer 5 is 0.....0000101 (32 bits). If you need just the resulting last bit after xor operation apply binary AND with 1:
<script>
console.log("%i\n",(5^0)&1);
console.log("%i\n",(6^0)&1);
</script>

how to calculate bitwise OR using AND, XOR and shift?

The question seems pretty well formulated
I have a virtual machine which implements only AND, XOR, SHL and SHR, yet I have to do a "OR 0x01" operation.
First of all having a correct bitwise computation for the following two variables is sufficient, because they cover all combinations:
A=0101
B=0011
We want
0101
0011
A or B
0111
for xor we get
0101
0011
A xor B
0110
for and we get
0101
0011
A and B
0001
so if we connect them with an xor we are done.
(A xor B) xor (A and B)
I would just start with
a xor b = ((not a) and b) or (a and (not b))
and unleash some boolean algebra on that until it looks like
a or b = <expression using only and, xor>
Admittedly, this is probably more work to actually do than going the "try every conceivable bit combination" route, but then you did ask for homework solution ideas. :)
The truth table as summarized on Wikipedia here and gasp, basic CS 101 stuff, De Morgan's Law....
AND
0 & 0 0
0 & 1 0
1 & 0 0
1 & 1 1
OR
0 | 0 0
0 | 1 1
1 | 0 1
0 | 0 1
XOR
0 ^ 0 0
0 ^ 1 1
1 ^ 0 1
1 ^ 1 0
A Shift Left involves shifting the bits across from right to left, suppose:
+-+-+-+-+-+-+-+-+
|7|6|5|4|3|2|1|0|
+-+-+-+-+-+-+-+-+
|0|0|0|0|0|1|0|0| = 0x4 hexadecimal or 4 decimal or 100 in binary
+-+-+-+-+-+-+-+-+
Shift Left by 2 places becomes
+-+-+-+-+-+-+-+-+
|7|6|5|4|3|2|1|0|
+-+-+-+-+-+-+-+-+
|0|0|0|1|0|0|0|0| = 0x10 hexadecimal or 16 decimal or 10000 in binary
+-+-+-+-+-+-+-+-+
Shift Right by 1 places becomes
+-+-+-+-+-+-+-+-+
|7|6|5|4|3|2|1|0|
+-+-+-+-+-+-+-+-+
|0|0|0|0|1|0|0|0| = 0x8 hexadecimal or 8 decimal or 1000 in binary
+-+-+-+-+-+-+-+-+
Then it is a matter of combining the bit-wise operations according to the truth table above...
I would just expand DeMorgan's law: A or B = not(not A and not B). You can compute not by XORing with all 1 bits.