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.
Related
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
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm struggling with the piece of code below, it's used to convert an integer into a binary. Can someone explain it more cearly? especially the '0'+
for (;d>0;d--){
buffer[index++] = '0'+ (x & 1);
x >>= 1;
}
First of all, "index" is initialized to 0. But what is the definition of "d"?
We have an array of characters named "buffer" and "x" is an integer to be converted.
Now, in "x & 1", "&" is Bitwise AND operator. If we operate "x & n", it changes the last n least significant bits as,
1 & 1 = 1,
1 & 0 = 0,
0 & 1 = 0,
0 & 0 = 0.
if we execute 4 & 1,
100
001
---
000
then, it returns 0.
if we execute 9 & 1,
1001
0001
----
0001
then, it returns 1.
Basically, if x is a even number x&1 returns 0, or returns 1 if x is odd.
Now, after that, this 0 or 1 is added to '0' (ascii 48), which is-
if x is even, '0' + (x & 1) stays '0', otherwise it becomes '1' as x&1 returns 1 and '0'+1 is '1'.
After that in "x >>= 1", ">>" is Bitwise right shift operator, which is equivalent to x = x / 2 or x /= 2. But there is little bit difference if we consider integers.
Consider x = 12, that is 1100 in binary.
if we execute x >>= 1, then x becomes 6, if shifts away last 0 of 1100, becomes 110.
again if we execute x >>= 1, then x becomes 3, if shifts away last 0 of 110, becomes 11.
again if we execute x >>= 1, then x becomes 1, if shifts away last 1 of 11, becomes 1.
again if we execute x >>= 1, then x becomes 0, if shifts away last 1 of 1, becomes 0.
Finally, if x is even it stores '0' in buffer[index], otherwise stores '1', until x is not 0.
This is a loop that starts with a variable containing some value and then creates a string of character digits of ones and zeros.
The '0' + (x & 1) takes the character for a digit zero '0' and then adds to that character the value of the right most bit of x which have either a value of zero or of one. If the bit is zero then the result of the addition is '0' and if the bit is one then the result of the addition is '1'.
This character is then put into the buffer, the variable x is right shifted by one bit to move the next binary digit to the right most place.
The addition is then repeated.
The result is that you have a text string of zeros and ones as character digits.
Are you sure this is the correct source code? Looks to me like the text string result would need to be reversed in order to correctly represent the binary value.
buffer[index++] = '0'+ (x & 1);
This line progresses through what is presumably a char array, setting each character to the character '0' PLUS a value that will be equal to either 0 or 1. '0' + 0 is ''0'. '0' + 1 is '1'. The reason x & 1 will be either 0 or 1 is because this code is essentially checking if the low bit is on in x. The reason this works is because the line below then right shifts x by 1, then sets x equal to that value, which basically is knocking off the low bit, and shifting all other bits over by 1. In this way, x is traversed, and each bit is checked.
Please note, however. It appears that it will be written BACKWARDS!
In ASCII 0 has the ASCII value 48 and 1 has the ASCII value 49. IOW if you write putchar(48); you see a 0 on the screen
The buffer presumably being a char 2-dimensional array is assigned
either 48 or 49 because x & 1 evaluates to either 1 or 0.
so say you have a value x = 225 and want to convert it to readable text containing 0's and 1's
225 looks like this in binary
1110 0001
when you do 1110 0001 & 0x1 you mask out the last 1 left is 0000 0001
so adding 1 to 48 and converting the sum ito a character is 1
next the bits are shifted one step right x >>= 1
0111 0000
masking that with 0x1 is 0000 0000
so adding 0 to 48 and converting the sum to a character becomes 0
and so on until x is 0
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.
What do "Non-Power-Of-Two Textures" mean? I read this tutorial and I meet some binaries operations("<<", ">>", "^", "~"), but I don't understand what they are doing.
For example following code:
GLuint LTexture::powerOfTwo(GLuint num)
{
if (num != 0)
{
num--;
num |= (num >> 1); //Or first 2 bits
num |= (num >> 2); //Or next 2 bits
num |= (num >> 4); //Or next 4 bits
num |= (num >> 8); //Or next 8 bits
num |= (num >> 16); //Or next 16 bits
num++;
}
return num;
}
I very want to understand this operations. As well, I read this. Very short article. I want to see examples of using, but I not found. I did the test:
int a = 5;
a <<= 1; //a = 10
a = 5;
a <<= 2; //a = 20
a = 5;
a <<= 3; //a = 40
Okay, this like multiply on two, but
int a = 5;
a >>= 1; // a = 2 Whaat??
In C++, the <<= is the "left binary shift" assignment operator; the operand on the left is treated as a binary number, the bits are moved to the left, and zero bits are inserted on the right.
The >>= is the right binary shift; bits are moved to the right and "fall off" the right end, so it's like a division by 2 (for each bit) but with truncation. For negative signed integers, by the way, additional 1 bits are shifted in at the left end ("arithmetic right shift"), which may be surprising; for positive signed integers, or unsigned integers, 0 bits are shifted in at the left ("logical right shift").
"Powers of two" are the numbers created by successive doublings of 1: 2, 4, 8, 16, 32… Most graphics hardware prefers to work with texture maps which are powers of two in size.
As said in http://lazyfoo.net/tutorials/OpenGL/08_non_power_of_2_textures/index.php
powerOfTwo will take the argument and find nearest number that is power of two.
GLuint powerOfTwo( GLuint num );
/*
Pre Condition:
-None
Post Condition:
-Returns nearest power of two integer that is greater
Side Effects:
-None
*/
Let's test:
num=60 (decimal) and its binary is 111100
num--; .. 59 111011
num |= (num >> 1); //Or first 2 bits 011101 | 111011 = 111111
num |= (num >> 2); //Or next 2 bits 001111 | 111111 = 111111
num |= (num >> 4); //Or next 4 bits 000011 | 111111 = 111111
num |= (num >> 8); //Or next 8 bits 000000 | 111111 = 111111
num |= (num >> 16); //Or next 16 bits 000000 | 111111 = 111111
num++; ..63+1 = 64
output 64.
For num=5: num-1 =4 (binary 0100), after all num |= (num >> N) it will be 0111 or 7 decimal). Then num+1 is equal to 8.
As you should know the data in our computers is represented in the binary system, in which digits are either a 1 or a 0.
So for example number 10 decimal = 1010 binary. (1*2^3 + 0*2^2 + 1*2^1 + 0*2^0).
Let's go to the operations now.
Binary | OR means that wherever you have at least one 1 the output will be 1.
1010
| 0100
------
1110
~ NOT means negation i.e. all 0s become 1s and all 1s become 0s.
~ 1010
------
0101
^ XOR means you turn a pair of 1 and 0 into a 1. All other combinations leave a 0 as output.
1010
^ 0110
------
1100
Bit shift.
N >> x means we "slide" our number N, x bits to the right.
1010 >> 1 = 0101(0) // zero in the brackets is dropped,
since it goes out of the representation = 0101
1001 >> 1 = 0100(1) // (1) is dropped = 0100
<< behaves the same way, just the opposite direction.
1000 << 1 = 0001
Since in binary system numbers are represented as powers of 2, shifting a bit one or the other direction will result in multiplying or dividing by 2.
Let num = 36. First subtract 1, giving 35. In binary, this is 100011.
Right shift by 1 position gives 10001 (the rightmost digit disappears). Bitwise Or'ed with num gives:
100011
10001
-------
110011
Note that this ensures two 1's on the left.
Now right shift by 2 positions, giving 1100. Bitwise Or:
110011
1100
-------
111111
This ensures four 1's on the left.
And so on, until the value is completely filled with 1's from the leftmost.
Add 1 and you get 1000000, a power of 2.
This procedure always generates a power of two, and you can check that it is just above the initial value of num.
I tried to understand how if condition work with bitwise operators.
A way to check if a number is even or odd can be done by:
#include <iostream>
#include <string>
using namespace std;
string test()
{
int i = 8; //a number
if(i & 1)
return "odd";
else
return "even";
}
int main ()
{
cout << test();
return 0;
}
The Part I don't understand is how the if condition work. In this case if i = 8 then the in If statement it is doing 1000 & 1 which should gives back 1000 which equal 8.
If i = 7, then in if statement it should be doing 111 & 1 which gives back 111 which equal 7
Why is it the case that if(8) will return "even" and if(7) return "odd"? I guess I want to understand what the if statement is checking to be True and what to be False when dealing with bit-wise operators.
Just A thought when I wrote this question down is it because it's actually doing
for 8: 1000 & 0001 which gives 0
for 7: 0111 & 0001 which gives 1?
Yes, you are right in the last part. Binary & and | are performed bit by bit. Since
1 & 1 == 1
1 & 0 == 0
0 & 1 == 0
0 & 0 == 0
we can see that:
8 & 1 == 1000 & 0001 == 0000
and
7 & 1 == 0111 & 0001 == 0001
Your test function does correctly compute whether a number is even or odd though, because a & 1 tests whether there is a 1 in the 1s place, which there only is for odd numbers.
Actually, in C, C++ and other major programming languages the & operator do AND operations in each bit for integral types. The nth bit in a bitwise AND is equal to 1 if and only if the nth bit of both operands are equal to 1.
For example:
8 & 1 =
1000 - 8
0001 - 1
----
0000 - 0
7 & 1 =
0111 - 7
0001 - 1
----
0001 - 1
7 & 5 =
0111 - 7
0101 - 5
----
0101 - 5
For this reason doing a bitwise AND between an even number and 1 will always be equal 0 because only odd numbers have their least significant bit equal to 1.
if(x) in C++ converts x to boolean. An integer is considered true iff it is nonzero.
Thus, all if(i & 1) is doing is checking to see if the least-significant bit is set in i. If it is set, i&1 will be nonzero; if it is not set, i&1 will be zero.
The least significant bit is set in an integer iff that integer is odd, so thus i&1 is nonzero iff i is odd.
What you say the code is doing is actually how bit-wise operators are supposed to work. In your example of (8 & 1):
1000 & 0001 = 0000
because in the first value, the last bit is set to 0, while in the second value, the last bit is set to 1. 0 & 1 = 0.
0111 & 0001 = 0001
In both values, the last bit is set to 1, so the result is 1 since 1 & 1 = 1.
The expression i & 1, where i is an int, has type int. Its value is 1 or 0, depending on the value of the low bit of i. In the statement if(i & 1), the result of that expression is converted to bool, following the usual rule for integer types: 0 becomes false and non-zero becomes true.