I am currently trying to gain a more intuitive understanding of two's complement and its uses; however, I cannot seem to perform subtraction using two's complement correctly. I understand that when a negative number is stored in a signed int variable the procedure is to perform two's complement on the number having the MSB be 1 to represent the negative sign.
So in a 4 bit system 1010 represents -6.
Now I am following this guide on how to subtract two binary #s
For example I have the number 0101 (5 in decimal) and 1010 (-6 in decimal). If I wanted to do the equation 5 - (-6) it would look like 0101 - 1010 in binary. Next I would take the 1010 and perform twos' complement on it to get 0110. Now I take 0101 + 0110 and get 1011. I don't have a carry so I perform two's complement on the result giving me 0101, but this says the answer is -5 when it should be 11.
4 bits can represent 16 different values. With two's complement, they are -8 to 7.
1000 -8
1001 -7
1010 -6
1011 -5
1100 -4
1101 -3
1110 -2
1111 -1
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
You can't possibly get an answer of 11. It's too large to fit in 4 bits as a two's complement number. As such, the calculation you are attempting results in an overflow. (See below for how to detect overflows.)
This means 4 bits is not enough to compute 5 - -6. You need at least 5 bits.
0(...0)0101 5
- 1(...1)1010 -6
------------------
0(...0)0101 5
+ 0(...0)0110 6
------------------
0(...0)1011 11
Detecting Overflow in Two's Complement
With two's complement numbers, an addition overflows when the carry into the sign bit is different than the carry out of it.
0101 5
+ 0110 6
-----------
1011 -5 Carry in: 1 Carry out: 0 OVERFLOW!
1011 -5
+ 1010 -6
-----------
0101 5 Carry in: 0 Carry out: 1 OVERFLOW!
0001 1
+ 0010 2
-----------
0011 3 Carry in: 0 Carry out: 0 No overflow
1111 -1
+ 1110 -2
-----------
1101 -3 Carry in: 1 Carry out: 1 No overflow
For example I have the number 0101 (5 in decimal) and 1010 (-6 in decimal). If I wanted to do the equation 5 - (-6) it would look like 0101 - 1010 in binary.
Ok.
Next I would take the 1010 and perform twos' complement on it to get 0110.
Ok. And 0110 binary is 6 decimal is -(-6) decimal.
Now I take 0101 + 0110 and get 1011.
Ok.
I don't have a carry so I perform two's complement on the result giving me 0101,
I take you to mean that as part of the process of interpreting the result, not computing it. The result itself is 1011 (4-bit, two's complement binary).
but this says the answer is -5 when it should be 11.
The answer in the operational system you have chosen, with 4-bit two's complement, is -5, exactly as you have computed. With three data bits and one sign bit, the maximum result your data type can represent is 7 (0111 binary). This underscores the importance of choosing data types appropriate for the computations you want to perform.
Note that 0b1011 is 11 in binary, if interpreted as unsigned or with more than 3 data bits, so both 11 and -5 are the result (which you use depends on how its interpreted).
In terms of modular arithmetic, 4 bits is a base of 24, and:
11 ≡ -5 (mod 16)
Which answer you use depends on whether the nibble is interpreted as signed or unsigned.
Related
I'm new to C++ and I find something I can't understand. Could anyone provide some help?
For the following codes:
int i = -3;
printf("i=%d\n",i);
i = i >> 1:
printf("i >> 1 evaluates to: %d\n", i);
then I got the result:
i=-3
i >> 1 evaluates to: -2
I don't quite understand.
As 3 is coded as( let is be simple):
3 : 0000 0011
-3 : 1111 1100
then after right shift operation, we should have:
-1 : 1111 1110
right? Why I got -2? (My PC in 64 bit)
Thanks for any help!
Your mistake is in assuming that because 3 is 00000011, -3 is represented simply by inverting bits (the so-called "one's complement" representation of negative numbers) to get 11111100. And that likewise 00000001 becomes 11111110 when negated. In fact that's not the case—instead your computer seems to be using the almost-universal "two's complement" system in which -3 is represented as 11111101, -2 is 11111110 and -1 is 11111111.
One nice intuition pump for the two's-complement system is to consider a series of increments, and to note that the behavior is somewhat consistent and intuitive regardless of whether you imagine them happening in the bit pattern itself, in the signed representation, or in the unsigned. Let's stick to 8 bits for simplicity (imagine the "9th bit" just getting discarded):
bit pattern interpreted as...
signed byte unsigned byte
11111101 -3 253
11111110 -2 254
11111111 -1 255
00000000 0 0 (wrap-around)
00000001 1 1
When it goes from -1 to 0 I can almost "hear" all those bits flipping over one after the other.
Actually -1 = 0xFFFF = 1111 1111 1111 1111b, -3 = 0xFFFD = 1111 1111 1111 1101b(for 4 byte int).
So when you use right shift, you get 1111 1111 1111 1110b which is -2
This question already has answers here:
What is “two's complement”?
(24 answers)
Closed 7 years ago.
I'm trying to understand why INT_MIN is equal to -2^31 - 1 and not just -2^31.
My understanding is that an int is 4 bytes = 32 bits. Of these 32 bits, I assume 1 bit is used for the +/- sign, leaving 31 bits for the actual value. As such, INT_MAX is equal to 2^31-1 = 2147483647. On the other hand, why is INT_MIN equal to -2^31 = -2147483648? Wouldn't this exceed the '4 bytes' allotted for int? Based on my logic, I would have expected INT_MIN to equal -2^31 = -2147483647
Most modern systems use two's complement to represent signed integer data types. In this representation, one state in the positive side is used up to represent zero, hence one positive value lesser than the negatives. In fact this is one of the prime advantage this system has over the sign-magnitude system, where zero has two representations, +0 and -0. Since zero has only one representation in two's complement, the other state, now free, is used to represent one more number.
Let's take a small data type, say 4 bits wide, to understand this better. The number of possible states with this toy integer type would be 2⁴ = 16 states. When using two's complement to represent signed numbers, we would have 8 negative and 7 positive numbers and zero; in sign-magnitude system, we'd get two zeros, 7 positive and 7 negative numbers.
Bin Dec
0000 = 0
0001 = 1
0010 = 2
0011 = 3
0100 = 4
0101 = 5
0110 = 6
0111 = 7
1000 = -8
1001 = -7
1010 = -6
1011 = -5
1100 = -4
1101 = -3
1110 = -2
1111 = -1
I think you are confused since you are imagining that sign-magnitude representation is used for signed numbers; although this is also allowed by the language standards, this system is very less likely to be implemented as two's complement system is significantly a better representation.
As of C++20, only two's complement is allowed for signed integers; source.
I don't understand why an n-bit 2C system number can be extended to an (n+1)-bit 2C system number by making bit bn = bn−1, that is, extending to (n+1) bits by replicating the sign bit.
This works because of the way we calculate the value of a binary integer.
Working right to left, the sum of each bit_i * 2 ^ i,
where
i is the range 0 to n
n is the number of bits
Because each subsequent 0 bit will not increase the magnitude of the sum, it is the appropriate value to pad a smaller value into a wider bit field.
For example, using the number 5:
4 bit: 0101
5 bit: 00101
6 bit: 000101
7 bit 0000101
8 bit: 00000101
The opposite is true for negative numbers in a two's compliment system.
Remember you calculate two's compliment by first calculating the one's compliment and then adding 1.
Invert the value from the previous example to get -5:
4 bit: 0101 (invert)-> 1010 + 1 -> 1011
5 bit: 00101 (invert)-> 11010 + 1 -> 11011
6 bit: 000101 (invert)-> 111010 + 1 -> 111011
7 bit: 0000101 (invert)-> 1111010 + 1 -> 1111011
8 bit: 00000101 (invert)-> 11111010 + 1 -> 11111011
I have problem: you know the 2s Complement so you can get the negative number of a positive one with the reverse and adding a one. e.g.
8 Bit
121 = 0111 1001
1st= 1000 0110
+ 0000 0001
---------
1000 0111 --> -121
So now if we have a -0
a zero looks as 8 bit
0000 0000
so a minus 0 should look
1111 1111 + 0000 0001
= 10000 0000
but that is 512
so I think that I've misunderstood something
To expand my previous comment to the question
1111 1111 + 0000 0001 in 8 bit is 0000 0000, the ninth bit is lost because there is no place from it.
And, yes the complement of a negative is a positive
-121 = 1000 0111
1st = 0111 1000
+ 0000 0001
---------
0111 1001 --> 121
Think of them as a circle, at one point there is 0, adding 1 at a time you go up to the opposite point (128 in 8 bit) at that point the sign is switched and the absolute value begin to decrease, e.g.: 128 + 1 = -127, as you continue to add 1 the value go back to 0 and the circle is completed.
So given a number of bit, you only have that much bit, no more, and if you want the value to be signed you really have only x-1 bit for the value, as the most significant bit is used for the sign (0 -> +; 1 -> -)
1 0000 0000b is 256, not 512. Truncated to 8 bits, it's 0.
This is because with two's complement, zero is zero. There is no positive or negative zero.
Compare this to one's complement or sign bit, where positive zero and negative zero are different values.
Going through the book "Cracking the coding interview" by Gayle Laakmann McDowell, in bit manipulation chapter, it posts a question:
Find the value of (assuming numbers are represented by 4 bits):
1011 & (~0 << 2)
Now, ~0 = 1 and shifting it two times towards the left yields 100 ( = 0100 to complete the 4 bits). Anding 1011 with 0100 equals 0000.
However, the answer i have is 1000.
~0 is not 1 but 1111 (or 0xf). The ~ operator is a bitwise NOT operator, and not a logical one (which would be !).
So, when shifted by 2 places to the left, the last four bits are 1100. And 1100 & 1011 is exaclty 1000.
~0 does not equal 1. The 0 will default to being an integer, and the NOT operation will reverse ALL the bits, not just the first.
~ is the Bitwise Complement Operator.
The value of ~0 should be 1111 in 4 bits .
1011 & (~0 << 2)
= 1011 & ( 1111 << 2)
= 1011 & 1100
= 1000
1011 & (~0 << 2)
~0 is not 1 but rather 11112 or 0xF16.
Shifting 1111 to the left twice gives 1100 (the two leftmost bits have been dropped and filled in with 0s from the right).
Adding 1011 & 1100 gives 1 in each bit position for which the corresponding bit position is 1, otherwise 0. This follows that the result is 1000.