Related
I am trying to understand how Java stores integer internally. I know all java primitive integers are signed, (except short?). That means one less bit available in a byte for the number.
My question is, are all integers (positive and negative) stored as two's complement or are only negative numbers in two's complement?
I see that the specs says x bit two's complement number. But I often get confused.
For instance:
int x = 15; // Stored as binary as is? 00000000 00000000 00000000 00001111?
int y = -22; // Stored as two complemented value? 11111111 11111111 11111111 11101010
Edit
To be clear, x = 15
In binary as is: `00000000 00000000 00000000 00001111'
Two's complement: `11111111 11111111 11111111 11110001`
So if your answer is all numbers are stored as two's complement then:
int x = 15; // 11111111 11111111 11111111 11110001
int y = -22 // 11111111 11111111 11111111 11101010
The confusion here again is the sign says, both are negative numbers. May be I am misreading / misunderstanding it?
Edit
Not sure my question is confusing. Forced to isolate the question:
My question precisely: Are positive numbers stored in binary as is while negative numbers are stored as two's complement?
Some said all are stored in two's complement and one answer says only negative numbers are stored as two's complement.
Let's start by summarizing Java primitive data types:
byte: Byte data type is an 8-bit signed two's complement integer.
Short: Short data type is a 16-bit signed two's complement integer.
int: Int data type is a 32-bit signed two's complement integer.
long: Long data type is a 64-bit signed two's complement integer.
float: Float data type is a single-precision 32-bit IEEE 754 floating point.
double: double data type is a double-precision 64-bit IEEE 754 floating point.
boolean: boolean data type represents one bit of information.
char: char data type is a single 16-bit Unicode character.
Source
Two's complement
"The good example is from wiki that the relationship to two's complement is realized by noting that 256 = 255 + 1, and (255 − x) is the ones' complement of x
0000 0111=7 two's complement is 1111 1001= -7
the way it works is the MSB(the most significant bit) receives a negative value so in the case above
-7 = 1001= -8 + 0+ 0+ 1
Positive integers are generally stored as simple binary numbers (1 is 1, 10 is 2, 11 is 3, and so on).
Negative integers are stored as the two's complement of their absolute value. The two's complement of a positive number is when using this notation a negative number.
Source
Since I received a few points for this answer, I decided to add more information to it.
A more detailed answer:
Among others there are four main approaches to represent positive and negative numbers in binary, namely:
Signed Magnitude
One's Complement
Two's Complement
Bias
1. Signed Magnitude
Uses the most significant bit to represent the sign, the remaining bits are used to represent the absolute value. Where 0 represents a positive number and 1 represents a negative number, example:
1011 = -3
0011 = +3
This representation is simpler. However, you cannot add binary numbers in the same way that you add decimal numbers, making it harder to be implemented at the hardware level. Moreover, this approach uses two binary patterns to represent the 0, -0 (1000) and +0 (0000).
2. One's Complement
In this representation, we invert all the bits of a given number to find out its complementary. For example:
010 = 2, so -2 = 101 (inverting all bits).
The problem with this representation is that there still exist two bits patterns to represent the 0, negative 0 (1111) and positive 0 (0000)
3. Two's Complement
To find the negative of a number, in this representation, we invert all the bits and then add one bit. Adding one bit solves the problem of having two bits patterns representing 0. In this representation, we only have one pattern for
0 (0000).
For example, we want to find the binary negative representation of 4 (decimal) using 4 bits. First, we convert 4 to binary:
4 = 0100
then we invert all the bits
0100 -> 1011
finally, we add one bit
1011 + 1 = 1100.
So 1100 is equivalent to -4 in decimal if we are using a Two's Complement binary representation with 4 bits.
A faster way to find the complementary is by fixing the first bit that as value 1 and inverting the remaining bits. In the above example it would be something like:
0100 -> 1100
^^
||-(fixing this value)
|--(inverting this one)
Two's Complement representation, besides having only one representation for 0, it also adds two binary values in the same way that in decimal, even numbers with different signs. Nevertheless, it is necessary to check for overflow cases.
4. Bias
This representation is used to represent the exponent in the IEEE 754 norm for floating points. It has the advantage that the binary value with all bits to zero represents the smallest value. And the binary value with all bits to 1 represents the biggest value. As the name indicates, the value is encoded (positive or negative) in binary with n bits with a bias (normally 2^(n-1) or 2^(n-1)-1).
So if we are using 8 bits, the value 1 in decimal is represented in binary using a bias of 2^(n-1), by the value:
+1 + bias = +1 + 2^(8-1) = 1 + 128 = 129
converting to binary
1000 0001
Java integers are of 32 bits, and always signed. This means, the most significant bit (MSB) works as the sign bit. The integer represented by an int is nothing but the weighted sum of the bits. The weights are assigned as follows:
Bit# Weight
31 -2^31
30 2^30
29 2^29
... ...
2 2^2
1 2^1
0 2^0
Note that the weight of the MSB is negative (the largest possible negative actually), so when this bit is on, the whole number (the weighted sum) becomes negative.
Let's simulate it with 4-bit numbers:
Binary Weighted sum Integer value
0000 0 + 0 + 0 + 0 0
0001 0 + 0 + 0 + 2^0 1
0010 0 + 0 + 2^1 + 0 2
0011 0 + 0 + 2^1 + 2^0 3
0100 0 + 2^2 + 0 + 0 4
0101 0 + 2^2 + 0 + 2^0 5
0110 0 + 2^2 + 2^1 + 0 6
0111 0 + 2^2 + 2^1 + 2^0 7 -> the most positive value
1000 -2^3 + 0 + 0 + 0 -8 -> the most negative value
1001 -2^3 + 0 + 0 + 2^0 -7
1010 -2^3 + 0 + 2^1 + 0 -6
1011 -2^3 + 0 + 2^1 + 2^0 -5
1100 -2^3 + 2^2 + 0 + 0 -4
1101 -2^3 + 2^2 + 0 + 2^0 -3
1110 -2^3 + 2^2 + 2^1 + 0 -2
1111 -2^3 + 2^2 + 2^1 + 2^0 -1
So, the two's complement thing is not an exclusive scheme for representing negative integers, rather we can say that the binary representation of integers are always the same, we just negate the weight of the most significant bit. And that bit determines the sign of the integer.
In C, there is a keyword unsigned (not available in java), which can be used for declaring unsigned int x;. In the unsigned integers, the weight of the MSB is positive (2^31) rather than being negative. In that case the range of an unsigned int is 0 to 2^32 - 1, while an int has range -2^31 to 2^31 - 1.
From another point of view, if you consider the two's complement of x as ~x + 1 (NOT x plus one), here's the explanation:
For any x, ~x is just the bitwise inverse of x, so wherever x has a 1-bit, ~x will have a 0-bit there (and vice versa). So, if you add these up, there will be no carry in the addition and the sum will be just an integer every bit of which is 1.
For 32-bit integers:
x + ~x = 1111 1111 1111 1111 1111 1111 1111 1111
x + ~x + 1 = 1111 1111 1111 1111 1111 1111 1111 1111 + 1
= 1 0000 0000 0000 0000 0000 0000 0000 0000
The leftmost 1-bit will simply be discarded, because it doesn't fit in 32-bits (integer overflow). So,
x + ~x + 1 = 0
-x = ~x + 1
So you can see that the negative x can be represented by ~x + 1, which we call the two's complement of x.
I have ran the following program to know it
public class Negative {
public static void main(String[] args) {
int i =10;
int j = -10;
System.out.println(Integer.toBinaryString(i));
System.out.println(Integer.toBinaryString(j));
}
}
Output is
1010
11111111111111111111111111110110
From the output it seems that it has been using two's complement.
Oracle provides some documentation regarding Java Datatypes that you may find interesting. Specifically:
int: The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive).
Btw, short is also stored as two's complement.
Positive numbers are stored/retrived as it is.
e.g) For +ve number 10; byte representation will be like 0-000 0010
(0 - MSB will represent that it is +ve).
So while retrieving based on MSB; it says it is +ve,
so the value will be taken as it is.
But negative numbers will be stored after 2's complement (other than
MSB bit), and MSB bit will be set to 1.
e.g) when storing -10 then
0-000 0010 -> (1's complement) -> 0-111 1101
-> (2's complement) 0-111 1101 + 1 -> 0-111 1110
Now MSB will be set to one, since it is negative no -> 1-111 1110
when retrieving, it found that MSB is set to 1. So it is negative no.
And 2's complement will be performed other than MSB.
1-111 1110 --> 1-000 0001 + 1 --> 1-000 0010
Since MSB representing this is negative 10 --> hence -10 will be retrived.
Casting
Also note that when you are casting int/short to byte, only last byte will be considered along with last byte MSB,
Take example "-130" short, it might be stored like below
(MSB)1-(2's complement of)130(1000 0010) --> 1-111 1111 0111 1110
Now byte casting took last byte which is 0111 1110. (0-MSB)
Since MSB says it is +ve value, so it will be taken as it is.
Which is 126. (+ve).
Take another example "130" short, it might be stored like below
0-000 000 1000 0010 (MSB = 0)
Now byte casting took last byte which is 1000 0010 . (1=MSB)
Since MSB says it is -ve value, 2's complement will be performed and negative number will be returned. So in this case -126 will be returned.
1-000 0010 -> (1's complement) -> 1-111 1101
-> (2's complement) 1-111 1101 + 1 -> 1-111 1110 -> (-)111 1110
= -126
Diff between (int)(char)(byte) -1 AND (int)(short)(byte) -1
(byte)-1 -> 0-000 0001 (2's Comp) -> 0-111 1111 (add sign) -> 1-111 1111
(char)(byte)-1 -> 1-111 1111 1111 1111 (sign bit is carry forwarded on left)
similarly
(short)(byte)-1-> 1-111 1111 1111 1111 (sign bit is carry forwarded on left)
But
(int)(char)(byte)-1 -> 0-0000000 00000000 11111111 11111111 = 65535
since char is unsigned; MSB won't be carry forwarded.
AND
(int)(Short)(byte)-1 -> 1-1111111 11111111 11111111 11111111 = -1
since short is signed; MSB is be carry forwarded.
References
Why is two's complement used to represent negative numbers?
What is “2's Complement”?
The most significant bit (32nd) indicates that the number is positive or negative. If it is 0, it means the number is positive and it is stored in its actual binary representation. but if it is 1, it means the number is negative and is stored in its two's complement representation. So when we give weight -2^32 to the 32nd bit while restoring the integer value from its binary representation, We get the actual answer.
According to this document, all integers are signed and stored in two's complement format for java. Not certain of its reliability..
positive numbers are stored directly as binary. 2's compliment is required for negative numbers.
for example:
15 : 00000000 00000000 00000000 00001111
-15: 11111111 11111111 11111111 11110001
here is the difference in signed bit.
Thank you, dreamcrash for the answer https://stackoverflow.com/a/13422442/1065835; on the wiki page they give an example which helped me understand how to find out the binary representation of the negative counterpart of a positive number.
For example, using 1 byte (= 2 nibbles = 8 bits), the decimal number 5
is represented by
0000 01012 The most significant bit is 0, so the pattern represents a
non-negative value. To convert to −5 in two's-complement notation, the
bits are inverted; 0 becomes 1, and 1 becomes 0:
1111 1010 At this point, the numeral is the ones' complement of the
decimal value −5. To obtain the two's complement, 1 is added to the
result, giving:
1111 1011 The result is a signed binary number representing the
decimal value −5 in two's-complement form. The most significant bit is
1, so the value represented is negative.
For positive integer 2'complement value is same with MSB bit 0 (like +14 2'complement is 01110).
For only negative integer only we are calculating 2'complement value (-14= 10001+1 = 10010).
So final answer is both the values(+ve and -ve) are stored in 2'complement form only.
I am trying to understand how Java stores integer internally. I know all java primitive integers are signed, (except short?). That means one less bit available in a byte for the number.
My question is, are all integers (positive and negative) stored as two's complement or are only negative numbers in two's complement?
I see that the specs says x bit two's complement number. But I often get confused.
For instance:
int x = 15; // Stored as binary as is? 00000000 00000000 00000000 00001111?
int y = -22; // Stored as two complemented value? 11111111 11111111 11111111 11101010
Edit
To be clear, x = 15
In binary as is: `00000000 00000000 00000000 00001111'
Two's complement: `11111111 11111111 11111111 11110001`
So if your answer is all numbers are stored as two's complement then:
int x = 15; // 11111111 11111111 11111111 11110001
int y = -22 // 11111111 11111111 11111111 11101010
The confusion here again is the sign says, both are negative numbers. May be I am misreading / misunderstanding it?
Edit
Not sure my question is confusing. Forced to isolate the question:
My question precisely: Are positive numbers stored in binary as is while negative numbers are stored as two's complement?
Some said all are stored in two's complement and one answer says only negative numbers are stored as two's complement.
Let's start by summarizing Java primitive data types:
byte: Byte data type is an 8-bit signed two's complement integer.
Short: Short data type is a 16-bit signed two's complement integer.
int: Int data type is a 32-bit signed two's complement integer.
long: Long data type is a 64-bit signed two's complement integer.
float: Float data type is a single-precision 32-bit IEEE 754 floating point.
double: double data type is a double-precision 64-bit IEEE 754 floating point.
boolean: boolean data type represents one bit of information.
char: char data type is a single 16-bit Unicode character.
Source
Two's complement
"The good example is from wiki that the relationship to two's complement is realized by noting that 256 = 255 + 1, and (255 − x) is the ones' complement of x
0000 0111=7 two's complement is 1111 1001= -7
the way it works is the MSB(the most significant bit) receives a negative value so in the case above
-7 = 1001= -8 + 0+ 0+ 1
Positive integers are generally stored as simple binary numbers (1 is 1, 10 is 2, 11 is 3, and so on).
Negative integers are stored as the two's complement of their absolute value. The two's complement of a positive number is when using this notation a negative number.
Source
Since I received a few points for this answer, I decided to add more information to it.
A more detailed answer:
Among others there are four main approaches to represent positive and negative numbers in binary, namely:
Signed Magnitude
One's Complement
Two's Complement
Bias
1. Signed Magnitude
Uses the most significant bit to represent the sign, the remaining bits are used to represent the absolute value. Where 0 represents a positive number and 1 represents a negative number, example:
1011 = -3
0011 = +3
This representation is simpler. However, you cannot add binary numbers in the same way that you add decimal numbers, making it harder to be implemented at the hardware level. Moreover, this approach uses two binary patterns to represent the 0, -0 (1000) and +0 (0000).
2. One's Complement
In this representation, we invert all the bits of a given number to find out its complementary. For example:
010 = 2, so -2 = 101 (inverting all bits).
The problem with this representation is that there still exist two bits patterns to represent the 0, negative 0 (1111) and positive 0 (0000)
3. Two's Complement
To find the negative of a number, in this representation, we invert all the bits and then add one bit. Adding one bit solves the problem of having two bits patterns representing 0. In this representation, we only have one pattern for
0 (0000).
For example, we want to find the binary negative representation of 4 (decimal) using 4 bits. First, we convert 4 to binary:
4 = 0100
then we invert all the bits
0100 -> 1011
finally, we add one bit
1011 + 1 = 1100.
So 1100 is equivalent to -4 in decimal if we are using a Two's Complement binary representation with 4 bits.
A faster way to find the complementary is by fixing the first bit that as value 1 and inverting the remaining bits. In the above example it would be something like:
0100 -> 1100
^^
||-(fixing this value)
|--(inverting this one)
Two's Complement representation, besides having only one representation for 0, it also adds two binary values in the same way that in decimal, even numbers with different signs. Nevertheless, it is necessary to check for overflow cases.
4. Bias
This representation is used to represent the exponent in the IEEE 754 norm for floating points. It has the advantage that the binary value with all bits to zero represents the smallest value. And the binary value with all bits to 1 represents the biggest value. As the name indicates, the value is encoded (positive or negative) in binary with n bits with a bias (normally 2^(n-1) or 2^(n-1)-1).
So if we are using 8 bits, the value 1 in decimal is represented in binary using a bias of 2^(n-1), by the value:
+1 + bias = +1 + 2^(8-1) = 1 + 128 = 129
converting to binary
1000 0001
Java integers are of 32 bits, and always signed. This means, the most significant bit (MSB) works as the sign bit. The integer represented by an int is nothing but the weighted sum of the bits. The weights are assigned as follows:
Bit# Weight
31 -2^31
30 2^30
29 2^29
... ...
2 2^2
1 2^1
0 2^0
Note that the weight of the MSB is negative (the largest possible negative actually), so when this bit is on, the whole number (the weighted sum) becomes negative.
Let's simulate it with 4-bit numbers:
Binary Weighted sum Integer value
0000 0 + 0 + 0 + 0 0
0001 0 + 0 + 0 + 2^0 1
0010 0 + 0 + 2^1 + 0 2
0011 0 + 0 + 2^1 + 2^0 3
0100 0 + 2^2 + 0 + 0 4
0101 0 + 2^2 + 0 + 2^0 5
0110 0 + 2^2 + 2^1 + 0 6
0111 0 + 2^2 + 2^1 + 2^0 7 -> the most positive value
1000 -2^3 + 0 + 0 + 0 -8 -> the most negative value
1001 -2^3 + 0 + 0 + 2^0 -7
1010 -2^3 + 0 + 2^1 + 0 -6
1011 -2^3 + 0 + 2^1 + 2^0 -5
1100 -2^3 + 2^2 + 0 + 0 -4
1101 -2^3 + 2^2 + 0 + 2^0 -3
1110 -2^3 + 2^2 + 2^1 + 0 -2
1111 -2^3 + 2^2 + 2^1 + 2^0 -1
So, the two's complement thing is not an exclusive scheme for representing negative integers, rather we can say that the binary representation of integers are always the same, we just negate the weight of the most significant bit. And that bit determines the sign of the integer.
In C, there is a keyword unsigned (not available in java), which can be used for declaring unsigned int x;. In the unsigned integers, the weight of the MSB is positive (2^31) rather than being negative. In that case the range of an unsigned int is 0 to 2^32 - 1, while an int has range -2^31 to 2^31 - 1.
From another point of view, if you consider the two's complement of x as ~x + 1 (NOT x plus one), here's the explanation:
For any x, ~x is just the bitwise inverse of x, so wherever x has a 1-bit, ~x will have a 0-bit there (and vice versa). So, if you add these up, there will be no carry in the addition and the sum will be just an integer every bit of which is 1.
For 32-bit integers:
x + ~x = 1111 1111 1111 1111 1111 1111 1111 1111
x + ~x + 1 = 1111 1111 1111 1111 1111 1111 1111 1111 + 1
= 1 0000 0000 0000 0000 0000 0000 0000 0000
The leftmost 1-bit will simply be discarded, because it doesn't fit in 32-bits (integer overflow). So,
x + ~x + 1 = 0
-x = ~x + 1
So you can see that the negative x can be represented by ~x + 1, which we call the two's complement of x.
I have ran the following program to know it
public class Negative {
public static void main(String[] args) {
int i =10;
int j = -10;
System.out.println(Integer.toBinaryString(i));
System.out.println(Integer.toBinaryString(j));
}
}
Output is
1010
11111111111111111111111111110110
From the output it seems that it has been using two's complement.
Oracle provides some documentation regarding Java Datatypes that you may find interesting. Specifically:
int: The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive).
Btw, short is also stored as two's complement.
Positive numbers are stored/retrived as it is.
e.g) For +ve number 10; byte representation will be like 0-000 0010
(0 - MSB will represent that it is +ve).
So while retrieving based on MSB; it says it is +ve,
so the value will be taken as it is.
But negative numbers will be stored after 2's complement (other than
MSB bit), and MSB bit will be set to 1.
e.g) when storing -10 then
0-000 0010 -> (1's complement) -> 0-111 1101
-> (2's complement) 0-111 1101 + 1 -> 0-111 1110
Now MSB will be set to one, since it is negative no -> 1-111 1110
when retrieving, it found that MSB is set to 1. So it is negative no.
And 2's complement will be performed other than MSB.
1-111 1110 --> 1-000 0001 + 1 --> 1-000 0010
Since MSB representing this is negative 10 --> hence -10 will be retrived.
Casting
Also note that when you are casting int/short to byte, only last byte will be considered along with last byte MSB,
Take example "-130" short, it might be stored like below
(MSB)1-(2's complement of)130(1000 0010) --> 1-111 1111 0111 1110
Now byte casting took last byte which is 0111 1110. (0-MSB)
Since MSB says it is +ve value, so it will be taken as it is.
Which is 126. (+ve).
Take another example "130" short, it might be stored like below
0-000 000 1000 0010 (MSB = 0)
Now byte casting took last byte which is 1000 0010 . (1=MSB)
Since MSB says it is -ve value, 2's complement will be performed and negative number will be returned. So in this case -126 will be returned.
1-000 0010 -> (1's complement) -> 1-111 1101
-> (2's complement) 1-111 1101 + 1 -> 1-111 1110 -> (-)111 1110
= -126
Diff between (int)(char)(byte) -1 AND (int)(short)(byte) -1
(byte)-1 -> 0-000 0001 (2's Comp) -> 0-111 1111 (add sign) -> 1-111 1111
(char)(byte)-1 -> 1-111 1111 1111 1111 (sign bit is carry forwarded on left)
similarly
(short)(byte)-1-> 1-111 1111 1111 1111 (sign bit is carry forwarded on left)
But
(int)(char)(byte)-1 -> 0-0000000 00000000 11111111 11111111 = 65535
since char is unsigned; MSB won't be carry forwarded.
AND
(int)(Short)(byte)-1 -> 1-1111111 11111111 11111111 11111111 = -1
since short is signed; MSB is be carry forwarded.
References
Why is two's complement used to represent negative numbers?
What is “2's Complement”?
The most significant bit (32nd) indicates that the number is positive or negative. If it is 0, it means the number is positive and it is stored in its actual binary representation. but if it is 1, it means the number is negative and is stored in its two's complement representation. So when we give weight -2^32 to the 32nd bit while restoring the integer value from its binary representation, We get the actual answer.
According to this document, all integers are signed and stored in two's complement format for java. Not certain of its reliability..
positive numbers are stored directly as binary. 2's compliment is required for negative numbers.
for example:
15 : 00000000 00000000 00000000 00001111
-15: 11111111 11111111 11111111 11110001
here is the difference in signed bit.
Thank you, dreamcrash for the answer https://stackoverflow.com/a/13422442/1065835; on the wiki page they give an example which helped me understand how to find out the binary representation of the negative counterpart of a positive number.
For example, using 1 byte (= 2 nibbles = 8 bits), the decimal number 5
is represented by
0000 01012 The most significant bit is 0, so the pattern represents a
non-negative value. To convert to −5 in two's-complement notation, the
bits are inverted; 0 becomes 1, and 1 becomes 0:
1111 1010 At this point, the numeral is the ones' complement of the
decimal value −5. To obtain the two's complement, 1 is added to the
result, giving:
1111 1011 The result is a signed binary number representing the
decimal value −5 in two's-complement form. The most significant bit is
1, so the value represented is negative.
For positive integer 2'complement value is same with MSB bit 0 (like +14 2'complement is 01110).
For only negative integer only we are calculating 2'complement value (-14= 10001+1 = 10010).
So final answer is both the values(+ve and -ve) are stored in 2'complement form only.
I'm in a computer systems course and have been struggling, in part, with two's complement. I want to understand it, but everything I've read hasn't brought the picture together for me. I've read the Wikipedia article and various other articles, including my text book.
What is two's complement, how can we use it and how can it affect numbers during operations like casts (from signed to unsigned and vice versa), bit-wise operations and bit-shift operations?
Two's complement is a clever way of storing integers so that common math problems are very simple to implement.
To understand, you have to think of the numbers in binary.
It basically says,
for zero, use all 0's.
for positive integers, start counting up, with a maximum of 2(number of bits - 1)-1.
for negative integers, do exactly the same thing, but switch the role of 0's and 1's and count down (so instead of starting with 0000, start with 1111 - that's the "complement" part).
Let's try it with a mini-byte of 4 bits (we'll call it a nibble - 1/2 a byte).
0000 - zero
0001 - one
0010 - two
0011 - three
0100 to 0111 - four to seven
That's as far as we can go in positives. 23-1 = 7.
For negatives:
1111 - negative one
1110 - negative two
1101 - negative three
1100 to 1000 - negative four to negative eight
Note that you get one extra value for negatives (1000 = -8) that you don't for positives. This is because 0000 is used for zero. This can be considered as Number Line of computers.
Distinguishing between positive and negative numbers
Doing this, the first bit gets the role of the "sign" bit, as it can be used to distinguish between nonnegative and negative decimal values. If the most significant bit is 1, then the binary can be said to be negative, where as if the most significant bit (the leftmost) is 0, you can say the decimal value is nonnegative.
"Sign-magnitude" negative numbers just have the sign bit flipped of their positive counterparts, but this approach has to deal with interpreting 1000 (one 1 followed by all 0s) as "negative zero" which is confusing.
"Ones' complement" negative numbers are just the bit-complement of their positive counterparts, which also leads to a confusing "negative zero" with 1111 (all ones).
You will likely not have to deal with Ones' Complement or Sign-Magnitude integer representations unless you are working very close to the hardware.
I wonder if it could be explained any better than the Wikipedia article.
The basic problem that you are trying to solve with two's complement representation is the problem of storing negative integers.
First, consider an unsigned integer stored in 4 bits. You can have the following
0000 = 0
0001 = 1
0010 = 2
...
1111 = 15
These are unsigned because there is no indication of whether they are negative or positive.
Sign Magnitude and Excess Notation
To store negative numbers you can try a number of things. First, you can use sign magnitude notation which assigns the first bit as a sign bit to represent +/- and the remaining bits to represent the magnitude. So using 4 bits again and assuming that 1 means - and 0 means + then you have
0000 = +0
0001 = +1
0010 = +2
...
1000 = -0
1001 = -1
1111 = -7
So, you see the problem there? We have positive and negative 0. The bigger problem is adding and subtracting binary numbers. The circuits to add and subtract using sign magnitude will be very complex.
What is
0010
1001 +
----
?
Another system is excess notation. You can store negative numbers, you get rid of the two zeros problem but addition and subtraction remains difficult.
So along comes two's complement. Now you can store positive and negative integers and perform arithmetic with relative ease. There are a number of methods to convert a number into two's complement. Here's one.
Convert Decimal to Two's Complement
Convert the number to binary (ignore the sign for now)
e.g. 5 is 0101 and -5 is 0101
If the number is a positive number then you are done.
e.g. 5 is 0101 in binary using two's complement notation.
If the number is negative then
3.1 find the complement (invert 0's and 1's)
e.g. -5 is 0101 so finding the complement is 1010
3.2 Add 1 to the complement 1010 + 1 = 1011.
Therefore, -5 in two's complement is 1011.
So, what if you wanted to do 2 + (-3) in binary? 2 + (-3) is -1.
What would you have to do if you were using sign magnitude to add these numbers? 0010 + 1101 = ?
Using two's complement consider how easy it would be.
2 = 0010
-3 = 1101 +
-------------
-1 = 1111
Converting Two's Complement to Decimal
Converting 1111 to decimal:
The number starts with 1, so it's negative, so we find the complement of 1111, which is 0000.
Add 1 to 0000, and we obtain 0001.
Convert 0001 to decimal, which is 1.
Apply the sign = -1.
Tada!
Like most explanations I've seen, the ones above are clear about how to work with 2's complement, but don't really explain what they are mathematically. I'll try to do that, for integers at least, and I'll cover some background that's probably familiar first.
Recall how it works for decimal: 2345 is a way of writing 2 × 103 + 3 × 102 + 4 × 101 + 5 × 100.
In the same way, binary is a way of writing numbers using just 0 and 1 following the same general idea, but replacing those 10s above with 2s. Then in binary, 1111is a way of writing 1 × 23 + 1 × 22 + 1 × 21 + 1 × 20and if you work it out, that turns out to equal 15 (base 10). That's because it is 8+4+2+1 = 15.
This is all well and good for positive numbers. It even works for negative numbers if you're willing to just stick a minus sign in front of them, as humans do with decimal numbers. That can even be done in computers, sort of, but I haven't seen such a computer since the early 1970's. I'll leave the reasons for a different discussion.
For computers it turns out to be more efficient to use a complement representation for negative numbers. And here's something that is often overlooked. Complement notations involve some kind of reversal of the digits of the number, even the implied zeroes that come before a normal positive number. That's awkward, because the question arises: all of them? That could be an infinite number of digits to be considered.
Fortunately, computers don't represent infinities. Numbers are constrained to a particular length (or width, if you prefer). So let's return to positive binary numbers, but with a particular size. I'll use 8 digits ("bits") for these examples. So our binary number would really be 00001111or 0 × 27 + 0 × 26 + 0 × 25 + 0 × 24 + 1 × 23 + 1 × 22 + 1 × 21 + 1 × 20
To form the 2's complement negative, we first complement all the (binary) digits to form 11110000and add 1 to form 11110001but how are we to understand that to mean -15?
The answer is that we change the meaning of the high-order bit (the leftmost one). This bit will be a 1 for all negative numbers. The change will be to change the sign of its contribution to the value of the number it appears in. So now our 11110001 is understood to represent -1 × 27 + 1 × 26 + 1 × 25 + 1 × 24 + 0 × 23 + 0 × 22 + 0 × 21 + 1 × 20Notice that "-" in front of that expression? It means that the sign bit carries the weight -27, that is -128 (base 10). All the other positions retain the same weight they had in unsigned binary numbers.
Working out our -15, it is -128 + 64 + 32 + 16 + 1 Try it on your calculator. it's -15.
Of the three main ways that I've seen negative numbers represented in computers, 2's complement wins hands down for convenience in general use. It has an oddity, though. Since it's binary, there have to be an even number of possible bit combinations. Each positive number can be paired with its negative, but there's only one zero. Negating a zero gets you zero. So there's one more combination, the number with 1 in the sign bit and 0 everywhere else. The corresponding positive number would not fit in the number of bits being used.
What's even more odd about this number is that if you try to form its positive by complementing and adding one, you get the same negative number back. It seems natural that zero would do this, but this is unexpected and not at all the behavior we're used to because computers aside, we generally think of an unlimited supply of digits, not this fixed-length arithmetic.
This is like the tip of an iceberg of oddities. There's more lying in wait below the surface, but that's enough for this discussion. You could probably find more if you research "overflow" for fixed-point arithmetic. If you really want to get into it, you might also research "modular arithmetic".
2's complement is very useful for finding the value of a binary, however I thought of a much more concise way of solving such a problem(never seen anyone else publish it):
take a binary, for example: 1101 which is [assuming that space "1" is the sign] equal to -3.
using 2's complement we would do this...flip 1101 to 0010...add 0001 + 0010 ===> gives us 0011. 0011 in positive binary = 3. therefore 1101 = -3!
What I realized:
instead of all the flipping and adding, you can just do the basic method for solving for a positive binary(lets say 0101) is (23 * 0) + (22 * 1) + (21 * 0) + (20 * 1) = 5.
Do exactly the same concept with a negative!(with a small twist)
take 1101, for example:
for the first number instead of 23 * 1 = 8 , do -(23 * 1) = -8.
then continue as usual, doing -8 + (22 * 1) + (21 * 0) + (20 * 1) = -3
Imagine that you have a finite number of bits/trits/digits/whatever. You define 0 as all digits being 0, and count upwards naturally:
00
01
02
..
Eventually you will overflow.
98
99
00
We have two digits and can represent all numbers from 0 to 100. All those numbers are positive! Suppose we want to represent negative numbers too?
What we really have is a cycle. The number before 2 is 1. The number before 1 is 0. The number before 0 is... 99.
So, for simplicity, let's say that any number over 50 is negative. "0" through "49" represent 0 through 49. "99" is -1, "98" is -2, ... "50" is -50.
This representation is ten's complement. Computers typically use two's complement, which is the same except using bits instead of digits.
The nice thing about ten's complement is that addition just works. You do not need to do anything special to add positive and negative numbers!
I read a fantastic explanation on Reddit by jng, using the odometer as an analogy.
It is a useful convention. The same circuits and logic operations that
add / subtract positive numbers in binary still work on both positive
and negative numbers if using the convention, that's why it's so
useful and omnipresent.
Imagine the odometer of a car, it rolls around at (say) 99999. If you
increment 00000 you get 00001. If you decrement 00000, you get 99999
(due to the roll-around). If you add one back to 99999 it goes back to
00000. So it's useful to decide that 99999 represents -1. Likewise, it is very useful to decide that 99998 represents -2, and so on. You have
to stop somewhere, and also by convention, the top half of the numbers
are deemed to be negative (50000-99999), and the bottom half positive
just stand for themselves (00000-49999). As a result, the top digit
being 5-9 means the represented number is negative, and it being 0-4
means the represented is positive - exactly the same as the top bit
representing sign in a two's complement binary number.
Understanding this was hard for me too. Once I got it and went back to
re-read the books articles and explanations (there was no internet
back then), it turned out a lot of those describing it didn't really
understand it. I did write a book teaching assembly language after
that (which did sell quite well for 10 years).
Two complement is found out by adding one to 1'st complement of the given number.
Lets say we have to find out twos complement of 10101 then find its ones complement, that is, 01010 add 1 to this result, that is, 01010+1=01011, which is the final answer.
Lets get the answer 10 – 12 in binary form using 8 bits:
What we will really do is 10 + (-12)
We need to get the compliment part of 12 to subtract it from 10.
12 in binary is 00001100.
10 in binary is 00001010.
To get the compliment part of 12 we just reverse all the bits then add 1.
12 in binary reversed is 11110011. This is also the Inverse code (one's complement).
Now we need to add one, which is now 11110100.
So 11110100 is the compliment of 12! Easy when you think of it this way.
Now you can solve the above question of 10 - 12 in binary form.
00001010
11110100
-----------------
11111110
Looking at the two's complement system from a math point of view it really makes sense. In ten's complement, the idea is to essentially 'isolate' the difference.
Example: 63 - 24 = x
We add the complement of 24 which is really just (100 - 24). So really, all we are doing is adding 100 on both sides of the equation.
Now the equation is: 100 + 63 - 24 = x + 100, that is why we remove the 100 (or 10 or 1000 or whatever).
Due to the inconvenient situation of having to subtract one number from a long chain of zeroes, we use a 'diminished radix complement' system, in the decimal system, nine's complement.
When we are presented with a number subtracted from a big chain of nines, we just need to reverse the numbers.
Example: 99999 - 03275 = 96724
That is the reason, after nine's complement, we add 1. As you probably know from childhood math, 9 becomes 10 by 'stealing' 1. So basically it's just ten's complement that takes 1 from the difference.
In Binary, two's complement is equatable to ten's complement, while one's complement to nine's complement. The primary difference is that instead of trying to isolate the difference with powers of ten (adding 10, 100, etc. into the equation) we are trying to isolate the difference with powers of two.
It is for this reason that we invert the bits. Just like how our minuend is a chain of nines in decimal, our minuend is a chain of ones in binary.
Example: 111111 - 101001 = 010110
Because chains of ones are 1 below a nice power of two, they 'steal' 1 from the difference like nine's do in decimal.
When we are using negative binary number's, we are really just saying:
0000 - 0101 = x
1111 - 0101 = 1010
1111 + 0000 - 0101 = x + 1111
In order to 'isolate' x, we need to add 1 because 1111 is one away from 10000 and we remove the leading 1 because we just added it to the original difference.
1111 + 1 + 0000 - 0101 = x + 1111 + 1
10000 + 0000 - 0101 = x + 10000
Just remove 10000 from both sides to get x, it's basic algebra.
The word complement derives from completeness. In the decimal world the numerals 0 through 9 provide a complement (complete set) of numerals or numeric symbols to express all decimal numbers. In the binary world the numerals 0 and 1 provide a complement of numerals to express all binary numbers. In fact The symbols 0 and 1 must be used to represent everything (text, images, etc) as well as positive (0) and negative (1).
In our world the blank space to the left of number is considered as zero:
35=035=000000035.
In a computer storage location there is no blank space. All bits (binary digits) must be either 0 or 1. To efficiently use memory numbers may be stored as 8 bit, 16 bit, 32 bit, 64 bit, 128 bit representations. When a number that is stored as an 8 bit number is transferred to a 16 bit location the sign and magnitude (absolute value) must remain the same. Both 1's complement and 2's complement representations facilitate this.
As a noun:
Both 1's complement and 2's complement are binary representations of signed quantities where the most significant bit (the one on the left) is the sign bit. 0 is for positive and 1 is for negative.
2s complement does not mean negative. It means a signed quantity. As in decimal the magnitude is represented as the positive quantity. The structure uses sign extension to preserve the quantity when promoting to a register [] with more bits:
[0101]=[00101]=[00000000000101]=5 (base 10)
[1011]=[11011]=[11111111111011]=-5(base 10)
As a verb:
2's complement means to negate. It does not mean make negative. It means if negative make positive; if positive make negative. The magnitude is the absolute value:
if a >= 0 then |a| = a
if a < 0 then |a| = -a = 2scomplement of a
This ability allows efficient binary subtraction using negate then add.
a - b = a + (-b)
The official way to take the 1's complement is for each digit subtract its value from 1.
1'scomp(0101) = 1010.
This is the same as flipping or inverting each bit individually. This results in a negative zero which is not well loved so adding one to te 1's complement gets rid of the problem.
To negate or take the 2s complement first take the 1s complement then add 1.
Example 1 Example 2
0101 --original number 1101
1's comp 1010 0010
add 1 0001 0001
2's comp 1011 --negated number 0011
In the examples the negation works as well with sign extended numbers.
Adding:
1110 Carry 111110 Carry
0110 is the same as 000110
1111 111111
sum 0101 sum 000101
SUbtracting:
1110 Carry 00000 Carry
0110 is the same as 00110
-0111 +11001
---------- ----------
sum 0101 sum 11111
Notice that when working with 2's complement, blank space to the left of the number is filled with zeros for positive numbers butis filled with ones for negative numbers. The carry is always added and must be either a 1 or 0.
Cheers
2's complement is essentially a way of coming up with the additive inverse of a binary number. Ask yourself this: Given a number in binary form (present at a fixed length memory location), what bit pattern, when added to the original number (at the fixed length memory location), would make the result all zeros ? (at the same fixed length memory location). If we could come up with this bit pattern then that bit pattern would be the -ve representation (additive inverse) of the original number; as by definition adding a number to its additive inverse always results in zero. Example: take 5 which is 101 present inside a single 8 bit byte. Now the task is to come up with a bit pattern which when added to the given bit pattern (00000101) would result in all zeros at the memory location which is used to hold this 5 i.e. all 8 bits of the byte should be zero. To do that, start from the right most bit of 101 and for each individual bit, again ask the same question: What bit should I add to the current bit to make the result zero ? continue doing that taking in account the usual carry over. After we are done with the 3 right most places (the digits that define the original number without regard to the leading zeros) the last carry goes in the bit pattern of the additive inverse. Furthermore, since we are holding in the original number in a single 8 bit byte, all other leading bits in the additive inverse should also be 1's so that (and this is important) when the computer adds "the number" (represented using the 8 bit pattern) and its additive inverse using "that" storage type (a byte) the result in that byte would be all zeros.
1 1 1
----------
1 0 1
1 0 1 1 ---> additive inverse
---------
0 0 0
Many of the answers so far nicely explain why two's complement is used to represent negative numbers, but do not tell us what two's complement number is, particularly not why a '1' is added, and in fact often added in a wrong way.
The confusion comes from a poor understanding of the definition of a complement number. A complement is the missing part that would make something complete.
The radix complement of an n digit number x in radix b is, by definition, b^n-x.
In binary 4 is represented by 100, which has 3 digits (n=3) and a radix of 2 (b=2). So its radix complement is b^n-x = 2^3-4=8-4=4 (or 100 in binary).
However, in binary obtaining a radix's complement is not as easy as getting its diminished radix complement, which is defined as (b^n-1)-y, just 1 less than that of radix complement. To get a diminished radix complement, you simply flip all the digits.
100 -> 011 (diminished (one's) radix complement)
to obtain the radix (two's) complement, we simply add 1, as the definition defined.
011 +1 ->100 (two's complement).
Now with this new understanding, let's take a look of the example given by Vincent Ramdhanie (see above second response):
Converting 1111 to decimal:
The number starts with 1, so it's negative, so we find the complement of 1111, which is 0000.
Add 1 to 0000, and we obtain 0001.
Convert 0001 to decimal, which is 1.
Apply the sign = -1.
Tada!
Should be understood as:
The number starts with 1, so it's negative. So we know it is a two's complement of some value x. To find the x represented by its two's complement, we first need find its 1's complement.
two's complement of x: 1111
one's complement of x: 1111-1 ->1110;
x = 0001, (flip all digits)
Apply the sign -, and the answer =-x =-1.
I liked lavinio's answer, but shifting bits adds some complexity. Often there's a choice of moving bits while respecting the sign bit or while not respecting the sign bit. This is the choice between treating the numbers as signed (-8 to 7 for a nibble, -128 to 127 for bytes) or full-range unsigned numbers (0 to 15 for nibbles, 0 to 255 for bytes).
It is a clever means of encoding negative integers in such a way that approximately half of the combination of bits of a data type are reserved for negative integers, and the addition of most of the negative integers with their corresponding positive integers results in a carry overflow that leaves the result to be binary zero.
So, in 2's complement if one is 0x0001 then -1 is 0x1111, because that will result in a combined sum of 0x0000 (with an overflow of 1).
2’s Complements: When we add an extra one with the 1’s complements of a number we will get the 2’s complements. For example: 100101 it’s 1’s complement is 011010 and 2’s complement is 011010+1 = 011011 (By adding one with 1's complement) For more information
this article explain it graphically.
Two's complement is mainly used for the following reasons:
To avoid multiple representations of 0
To avoid keeping track of carry bit (as in one's complement) in case of an overflow.
Carrying out simple operations like addition and subtraction becomes easy.
Two's complement is one of the ways of expressing a negative number and most of the controllers and processors store a negative number in two's complement form.
In simple terms, two's complement is a way to store negative numbers in computer memory. Whereas positive numbers are stored as a normal binary number.
Let's consider this example,
The computer uses the binary number system to represent any number.
x = 5;
This is represented as 0101.
x = -5;
When the computer encounters the - sign, it computes its two's complement and stores it.
That is, 5 = 0101 and its two's complement is 1011.
The important rules the computer uses to process numbers are,
If the first bit is 1 then it must be a negative number.
If all the bits except first bit are 0 then it is a positive number, because there is no -0 in number system (1000 is not -0 instead it is positive 8).
If all the bits are 0 then it is 0.
Else it is a positive number.
To bitwise complement a number is to flip all the bits in it. To two’s complement it, we flip all the bits and add one.
Using 2’s complement representation for signed integers, we apply the 2’s complement operation to convert a positive number to its negative equivalent and vice versa. So using nibbles for an example, 0001 (1) becomes 1111 (-1) and applying the op again, returns to 0001.
The behaviour of the operation at zero is advantageous in giving a single representation for zero without special handling of positive and negative zeroes. 0000 complements to 1111, which when 1 is added. overflows to 0000, giving us one zero, rather than a positive and a negative one.
A key advantage of this representation is that the standard addition circuits for unsigned integers produce correct results when applied to them. For example adding 1 and -1 in nibbles: 0001 + 1111, the bits overflow out of the register, leaving behind 0000.
For a gentle introduction, the wonderful Computerphile have produced a video on the subject.
The question is 'What is “two's complement”?'
The simple answer for those wanting to understand it theoretically (and me seeking to complement the other more practical answers): 2's complement is the representation for negative integers in the dual system that does not require additional characters, such as + and -.
Two's complement of a given number is the number got by adding 1 with the ones' complement of the number.
Suppose, we have a binary number: 10111001101
Its 1's complement is: 01000110010
And its two's complement will be: 01000110011
Reference: Two's Complement (Thomas Finley)
I invert all the bits and add 1. Programmatically:
// In C++11
int _powers[] = {
1,
2,
4,
8,
16,
32,
64,
128
};
int value = 3;
int n_bits = 4;
int twos_complement = (value ^ ( _powers[n_bits]-1)) + 1;
You can also use an online calculator to calculate the two's complement binary representation of a decimal number: http://www.convertforfree.com/twos-complement-calculator/
The simplest answer:
1111 + 1 = (1)0000. So 1111 must be -1. Then -1 + 1 = 0.
It's perfect to understand these all for me.
Please, help me to understand binary presentation of negative integers.
For example we have 5.
Binary presentation of 5 is 00000000.00000000.00000000.00000101.
And as I understand binary presentation of -5 should be like 10000000.00000000.00000000.00000101.
But output is 11111111.11111111.11111111.11111011.
I have 2 question:
1) Why here is so much 1 bits.
2) What I really cant understand it last 3 bits 011. It looks like 3. Even +1 or -1 it'll be 100 or 010
Thanks
Your understanding of what those negative numbers should look like is flawed. Java uses two's complement for negative numbers and the basic rule is to take the positive, invert all bits then add one. That gets you the negative.
Hence five is, as you state:
0000...00000101
Inverting that gives you:
1111...11111010
Then adding one gives:
1111...11111011
The bit pattern you have shown for -5 is what's called sign/magnitude, where you negate a number simply by flipping the leftmost bit. That's allowed in C implementations as one of the three possibilities(a), but Java uses two's complement only (for its negative integers).
(a) But keep in mind there are current efforts in both C and C++ to remove the other two encoding types and allow only two's complement.
And as I understand binary presentation of -5 should be like 10000000.00000000.00000000.00000101.
That would be right if Java used a Sign and Magnitude representation for integers. However, Java uses Two's Complement representation, so the rest of the bits are changed in accordance with the rules of that representation.
The idea behind two's complement representation is that when you add a number in such representation to another value dropping the extra bit on the most significant end, the result would be as if you subtracted a positive number of the same magnitude.
You can illustrate this with decimal numbers. In a two-digit representation, the value of 99 would behave like -1, 98 would be like -2, 97 like -3, and so on. For example, if you drop the top digit in 23 + 99 = [1]22, so 99 behaved like -1. 23 + 98 = [1]21, so 98 behaved like -2.
This works the same way with two's complement representation of binary numbers, except you would drop the extra bit at the top.
http://en.wikipedia.org/wiki/Two%27s_complement
The way negative numbers are stored is that the most significant bit (e.g. the bit representing 2^31 for a 32 bit number) is regarded as negative. So if you stored all 1s, you would add up
(-2^31) + 2^30 + 2^29 + ... + 2^1 + 2^0
which makes -1.
Small negative numbers will be mostly ones under this representation.
Here is an example for 2's compliment:
If you have -30, and want to represent it in 2's complement, you take the binary representation of 30:
0000 0000 0000 0000 0000 0000 0001 1110
Invert the digits.
1111 1111 1111 1111 1111 1111 1110 0001
And add one.
1111 1111 1111 1111 1111 1111 1110 0010
Converted back into hex, this is 0xFFFFFFE2. And indeed, suppose you have this code:
#include <stdio.h>
int main() {
int myInt;
myInt = 0xFFFFFFE2;
printf("%d\n",myInt);
return 0;
}
That should yield an output of -30. Try it out if you like.
With two's complement it's true that a MSB of 1 indicates a negative number. But the remaining bits are not the binary representation of its value. On the other hand, if the MSB is 0 the remaining bits represent the binary value. But it cannot be said that the number is positive then. Zero is neither positive nor negative.
This picture helped me to understand the principle when I started to learn that there are more representations of numbers than with 0..9:
0
-1 000 1
111 001
-2 110 010 2
101 011
-3 100 3
-4
thank you in advance for this basic question.
I am going through a tutorial and I see this line.
int a = (n & 8) / 8
This is supposed to identify whether the fourth bit from the right is a binary representation of 0 or 1. I understand the concept of bits etc, but I do not understand what mathematical equation (if any) this represents.
Would anyone care to explain how this would be written in a mathematical equation? Also, please let me know if i am missing anything else in my understanding of this line. Thank you.
The expression ( n & 8 )
does Logical And of n with 1000 binary.
So that gets the 4th bit from right.
then dividing that by 8, shifts the value right 3 binary places. I.e. it moves the 4th bit to the rightmost place.
That is more clearly expressed as " >> 3"
So your overall expression would be something like:
(n AND 1000 ) >> 3
And that leaves the 4th bit of N in a temporary variable, as bit 0 (rightmost bit).
All the other bits will be zero because of the AND.
8 in decimal is 1000 in binary
so if you do bitwise AND with any number
n & 8
it will stay 8 only if the 4th bit is 1 and
if you divide it by 8 again it will return 1, zero otherwise
For example
for 9 (1001)
9 & 8
would be
1001
& 1000
------
1000
Now for the case where forth bit is 0
for 7 (0111)
7 & 8
would be
0111
& 1000
-----
0000
int a = (n & 8) / 8;
The n & 8 applys a logical AND mask to the 4th bit of n;
n: 11001010 // example value
8: 00001000
result: 00001000
Dividing that number by 8 brings the result to the lowest bit :
result: 00000001
Dividing a number by 2^n shifts the numbers n bits to the right (in the same way that multiplying by 2^n shifts bits to the left).
The result is assigned to variable a, which now contains 0 or 1, depending on the value of the 4th bit.
Bitwise operator works on bits and performs bit-by-bit operation. Assume if a = 60; and b = 13; now in binary format they will be as follows:
a = 0011 1100
b = 0000 1101
a&b=0000 1100
then a&b is also an integer which is further divided by 8 in your example.