Calculating 2's compliment of a number [duplicate] - c

This question already has answers here:
How to take twos complement of a byte in c++?
(4 answers)
Closed 6 years ago.
I was working on converting 60 to 2's complement. This is how I did:
60 to binary 00111100
1's compliment 11000011
2's compliment 11000100 (by adding 1 to the 1's compliment)
When I execute this in a program using the following piece of code
#define NUM 60
unsigned char c;
c=~NUM;
printf("%d",c);
it prints 195 not 196. Please explain the reason behind this? Also explain process of calculating (~) of any given number.

The expression ~NUM is not strictly portable. To calculate your ones complement, you could try subtracting from UCHAR_MAX instead, for example: c = UCHAR_MAX - NUM;. This will work portably because according to the standard, UCHAR_MAX is required to be a binary power minus one:
The value UCHAR_MAX shall equal 2CHAR_BIT - 1.
Don't forget to increment c afterwards, as in your final step on paper: c++.
You could safely perform the entire twos complement operation in one step, providing your underlying choice of representation is unsigned (which it should be, because the whole idea of twos complement is to represent signed integers on an unsigned group of bits): c = -NUM;. This is because negative numbers are converted to unsigned types using the following procedure also described within the C11 standard:
... if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
In this case that repeatedly happens to be once: -60 + UCHAR_MAX + 1 == 196 when UCHAR_MAX == 255. If we were talking about a larger value, such as -32767 then multiple such additions would be required.
On that note, if you need to operate with numbers greater than 32768 for NUM, you'll want to think about different suffixes, for example #define NUM 32768L would be sufficient, and much larger than that #define NUM 2147483648LL.

The operator ~ performs a logical not giving back the 1's complement, not the 2's complement.
To perform the 2's complement in C use the - unary minus. See the following example:
#define NUM 60
char c1 = ~NUM; //1's complement
char c2 = -NUM; //2's complement
printf("NUM=%d, 1's complement=%d, 2's complement=%d\n",NUM, c1, c2);
But the main point is that you cannot perform a 2's complement on an unsigned type, because by default the 2's complement is used to find the representation of the same negative number. I.e. 2 -2, 10 -10, 5 -5, etc.
Consider that the values you are looking for are the unsigned representation of the negative (2's complement) value. I.e. adding:
printf("2's complementunsigned representation=%d\n", (unsigned char)c2);
Will print 196, that is -60, read as an unsigned value.

The symbol ~ calculates the 1's complement of the number. You just have to add 1 to the calculation.
c = ~NUM + 1;
Your description of the process of calculating the 1's complement is correct. To know more about it visit the wiki page on 1's complement.
Cheers!

The ~ gives you the one's complement. Use negate (-) to get the two's complement.
#include <stdio.h>
#define NUM0 0
#define NUM60 60
int main() {
unsigned char b;
unsigned char c;
b = ~NUM0;
c = -NUM0;
printf( "b=%d c=%d", b, c );
b = ~NUM60;
c = -NUM60;
printf( "b=%d c=%d", b, c );
}
outputs:
b=255 c=0
b=195 c=196

Related

How to get two's complement of an int in C? [duplicate]

This question already has answers here:
Display the binary representation of a number in C? [duplicate]
(8 answers)
Closed 6 years ago.
How do you get the Two's complement for a int in C?
Say for example I had an int such as -254, how would I go about converting this to 100000010?
Is there any way to pull out the Two's complement value from the integer variable, as I know that in C, the ints are stored in Two's comp?
If you're operating on unsigned ints then you can invert the bits ~ and add 1 to yield the 2s complement value. x=(~y)+1; If your machine uses a 2s complement representation for signed int then this should convert (by the implementation's definition) to the proper signed int value.
The C language itself is a little vague in its guarantees in this area. To work portably on the bitwise representation of an object you should use an unsigned type.
know that in C, the ints are stored in Two's comp
Not guaranteed, but in practice every computer uses two's complement.
Is there any way to pull out the Two's complement value from the integer variable
It is already in two's complement format, so it is unclear what you are asking. It would seem you are asking how to print a variable in binary format?
int data = -254;
const size_t BITS = 8*sizeof(data);
char bin_str[BITS+1];
for(unsigned int i=0; i<BITS; i++)
{
unsigned int mask = 1u << (BITS - 1 - i);
bin_str[i] = (data & mask) ? '1' : '0';
}
bin_str[BITS] = '\0';
You can convert signed-magnitude to two's complement by subtracting the number from 0x80000000 if the number is negative. This will work for a 32-bit integer on a machine using two's complement to represent negative values, but if the value is positive this will result in a two's complement negation. A right shift of a two's complement negative number will shift in one's, we can utilize this to make a mask to select between the original value, or the conversion of a signed-magnitude negative value to a two's complement negative value.
int sm2tc(int x) {
int m = x >> 31;
return (~m & x) | (((x & 0x80000000) - x) & m);
}
Original Code posted by Apriori
Actually, there is an easy way to do this. Simply convert your number to a binary string, and convert that string back to an integer.
Use itoa, which converts a number to its given base in string form.
http://www.cplusplus.com/reference/cstdlib/itoa/
Then, simply use the familiar atoi that converts it back to an int.

Difference between unsigned int and int

I read about twos complement on wikipedia and on stack overflow, this is what I understood but I'm not sure if it's correct
signed int
the left most bit is interpreted as -231 and this how we can have negative numbers
unsigned int
the left most bit is interpreted as +231 and this is how we achieve large positive numbers
update
What will the compiler see when we store 3 vs -3?
I thought 3 is always 00000000000000000000000000000011
and -3 is always 11111111111111111111111111111101
example for 3 vs -3 in C:
unsigned int x = -3;
int y = 3;
printf("%d %d\n", x, y); // -3 3
printf("%u %u\n", x, y); // 4294967293 3
printf("%x %x\n", x, y); // fffffffd 3
Two's complement is a way to represent negative integers in binary.
First of all, here's a standard 32-bit integer ranges:
Signed = -(2 ^ 31) to ((2 ^ 31) - 1)
Unsigned = 0 to ((2 ^ 32) - 1)
In two's complement, a negative is represented by inverting the bits of its positive equivalent and adding 1:
10 which is 00001010 becomes -10 which is 11110110 (if the numbers were 8-bit integers).
Also, the binary representation is only important if you plan on using bitwise operators.
If your doing basic arithmetic, then this is unimportant.
The only time this may give unexpected results outside of the aforementioned times is getting the absolute value of the signed version of -(2 << 31) which will always give a negative.
Your problem does not have to do with the representation, but the type.
A negative number in an unsigned integer is represented the same, the difference is that it becomes a super high number since it must be positive and the sign bit works as normal.
You should also realize that ((2^32) - 5) is the exact same thing as -5 if the value is unsigned, etc.
Therefore, the following holds true:
unsigned int x = (2 << 31) - 5;
unsigned int y = -5;
if (x == y) {
printf("Negative values wrap around in unsigned integers on underflow.");
}
else {
printf( "Unsigned integer underflow is undefined!" );
}
The numbers don't change, just the interpretation of the numbers. For most two's complement processors, add and subtract do the same math, but set a carry / borrow status assuming the numbers are unsigned, and an overflow status assuming the number are signed. For multiply and divide, the result may be different between signed and unsigned numbers (if one or both numbers are negative), so there are separate signed and unsigned versions of multiply and divide.
For 32-bit integers, for both signed and unsigned numbers, n-th bit is always interpreted as +2n.
For signed numbers with the 31th bit set, the result is adjusted by -232.
Example:
1111 1111 1111 1111 1111 1111 1111 11112 as unsigned int is interpreted as 231+230+...+21+20. The interpretation of this as a signed int would be the same MINUS 232, i.e. 231+230+...+21+20-232 = -1.
(Well, it can be said that for signed numbers with the 31th bit set, this bit is interpreted as -231 instead of +231, like you said in the question. I find this way a little less clear.)
Your representation of 3 and -3 is correct: 3 = 0x00000003, -3 + 232 = 0xFFFFFFFD.
Yes, you are correct, allow me to explain a bit further for clarification purposes.
The difference between int and unsigned int is how the bits are interpreted. The machine processes unsigned and signed bits the same way, but there are extra bits added for signing. Two's complement notation is very readable when dealing with related subjects.
Example:
The number 5's, 0101, inverse is 1011.
In C++, it's depends when you should use each data type. You should use unsigned values when functions or operators return those values. ALUs handle signed and unsigned variables very similarly.
The exact rules for writing in Two's complement is as follows:
If the number is positive, count up to 2^(32-1) -1
If it is 0, use all zeroes
For negatives, flip and switch all the 1's and 0's.
Example 2(The beauty of Two's complement):
-2 + 2 = 0 is displayed as 0010 + 1110; and that is 10000. With overflow at the end, we have our result as 0000;

Using bit mask to convert a signed integer into two's complement

I am given this code to convert a signed integer into two's complement but I don't understand how it really works, especially if the input is negative.
void convertB2T( int32_t num) {
uint8_t bInt[32];
int32_t mask = 0x01;
for (int position = 0; position < NUM_BITS; position++) {
bInt[position] = ( num & Mask) ? 1 : 0;
Mask = Mask << 1;
}
}
So my questions are:
num is an integer, Mask is a hex, so how does num & Mask work? Does C just convert num to binary representation and do the bitwise and? Also the output of Mask is an integer correct? So if this output is non-zero, it is treated as TRUE and if zero, FALSE, right?
How does this work if num is negative? I tried running the code and actually did not get a correct answer (all higher level bits are 1's).
This program basically extracts each bit of the number and puts it in a vector. So every bit becomes a vector element. It has nothing to do with two's complement conversion (although the resulting bit-vector will be in two's complement, as the internal representation of numbers is in two's complement).
The computer has no idea what hex means. Every value is stored in binary, because binary is the only thing computer understands. So, ,the "integer" and the hex values are converted to binary (the hex there is also an integer). On these binary representations that the computer uses, the binary operators are applied.
In order to understand what is happening with the result when num is negative, you need to understand that the result is basically the two's complement representation of num and you need to know how the two's complement representation works. Wikipedia is a good starting point.
To answer your questions
1.Yes num is integer represented in decimal format and mask is also integer represented in hex format.
Yes C compiler treats num and mask with their binary equivalents.
Say
num = 24; // binary value on 32 bit machine is 000000000000000000011000
mask = 0x01; // binary value on 32 bit machine is 000000000000000000000001
Yes compiler now performs & bitwise and the equivalent binary values.
Yes if output is nonzero, treated as true
If a number is negative, its represented in 2's complement form.
Basically your code is just storing binary equivalent of number into array. You are not representing in twos complement.
If MSB is 1 indicates number is negative. if a number is negative
num = -24; // represent binary value of 24
000000000000000000011000 -> apply 1's complement + 1 to this binary value
111111111111111111100111 -> 1's complement
+000000000000000000000001 -> add 1
------------------------
111111111111111111101000 -> -24 representation
------------------------

C programming bitfield in structure

Why is answer of it
-1, 2, -3 ? (especially -3 ??? how come)
struct b1 {
int a:1;
int b:3;
int c:4;
} ;
int main()
{
struct b1 c = {1,2,13};
printf("%d, %d, %d",c.a,c.b,c.c);
return 0;
}
Compiled on VC++ 32 bit editor. Many Thanks.
signed integers are represented in twos complement. The range of a 1-bit twos complement number is -1 to 0. Because the first bit of a twos complement number indicates it is negative, which is what you have done there.
See here:
sign extend 1-bit 2's complement number?
That is the same for the third number, you have overflowed the range of -8 to 7 which is the range of a 4 bit signed integer.
What you meant to do there is make all of those int -> unsigned int
See here for twos complement explanation:
http://www.ele.uri.edu/courses/ele447/proj_pages/divid/twos.html
Because a and c are signed integers with their sign bit set, hence they are negative:
a: 1d = 1b (1 bit)
b: 2d = 010b (3 bits)
c: 13d = 1101b (4 bits)
Signed integer values are stored in two's complement, with the highest bit representing the sign (1 means "negative"). Hence, when you read the bitfield values as signed int's, you get back negative values for a and c (sign extended and converted back from their two's complement representation), but a positive 2 for b.
To get the absolute value of a negative two's complement number, you subtract one and invert the result:
1101b
-0001b
======
1100b
1100b inverted becomes 0011b which is equal to 3d. Since the sign bit is negative (which you had to examine before doing the previous calculation anyway), the result is -3d.

Tilde C unsigned vs signed integer

For example:
unsigned int i = ~0;
Result: Max number I can assign to i
and
signed int y = ~0;
Result: -1
Why do I get -1? Shouldn't I get the maximum number that I can assign to y?
Both 4294967295 (a.k.a. UINT_MAX) and -1 have the same binary representation of 0xFFFFFFFF or 32 bits all set to 1. This is because signed numbers are represented using two's complement. A negative number has its MSB (most significant bit) set to 1 and its value determined by flipping the rest of the bits, adding 1 and multiplying by -1. So if you have the MSB set to 1 and the rest of the bits also set to 1, you flip them (get 32 zeros), add 1 (get 1) and multiply by -1 to finally get -1.
This makes it easier for the CPU to do the math as it needs no special exceptions for negative numbers. For example, try adding 0xFFFFFFFF (-1) and 1. Since there is only room for 32 bits, this will overflow and the result will be 0 as expected.
See more at:
http://en.wikipedia.org/wiki/Two%27s_complement
unsigned int i = ~0;
Result: Max number I can assign to i
Usually, but not necessarily. The expression ~0 evaluates to an int with all (non-padding) bits set. The C standard allows three representations for signed integers,
two's complement, in which case ~0 = -1 and assigning that to an unsigned int results in (-1) + (UINT_MAX + 1) = UINT_MAX.
ones' complement, in which case ~0 is either a negative zero or a trap representation; if it's a negative zero, the assignment to an unsigned int results in 0.
sign-and-magnitude, in which case ~0 is INT_MIN == -INT_MAX, and assigning it to an unsigned int results in (UINT_MAX + 1) - INT_MAX, which is 1 in the unlikely case that unsigned int has a width (number of value bits for unsigned integer types, number of value bits + 1 [for the sign bit] for signed integer types) smaller than that of int and 2^(WIDTH - 1) + 1 in the common case that the width of unsigned int is the same as the width of int.
The initialisation
unsigned int i = ~0u;
will always result in i holding the value UINT_MAX.
signed int y = ~0;
Result: -1
As stated above, only if the representation of signed integers uses two's complement (which nowadays is by far the most common representation).
~0 is just an int with all bits set to 1. When interpreted as unsigned this will be equivalent to UINT_MAX. When interpreted as signed this will be -1.
Assuming 32 bit ints:
0 = 0x00000000 = 0 (signed) = 0 (unsigned)
~0 = 0xffffffff = -1 (signed) = UINT_MAX (unsigned)
Paul's answer is absolutely right. Instead of using ~0, you can use:
#include <limits.h>
signed int y = INT_MAX;
unsigned int x = UINT_MAX;
And now if you check values:
printf("x = %u\ny = %d\n", UINT_MAX, INT_MAX);
you can see max values on your system.
No, because ~ is the bitwise NOT operator, not the maximum value for type operator. ~0 corresponds to an int with all bits set to 1, which, interpreted as an unsigned gives you the max number representable by an unsigned, and interpreted as a signed int, gives you -1.
You must be on a two's complement machine.
Look up http://en.wikipedia.org/wiki/Two%27s_complement, and learn a little about Boolean algebra, and logic design. Also learning how to count in binary and addition and subtraction in binary will explain this further.
The C language used this form of numbers so to find the largest number you need to use 0x7FFFFFFF. (where you use 2 FF's for each byte used and the leftmost byte is a 7.) To understand this you need to look up hexadecimal numbers and how they work.
Now to explain the unsigned equivalent. In signed numbers the bottom half of numbers are negative (0 is assumed positive so negative numbers actually count 1 higher than positive numbers). Unsigned numbers are all positive. So in theory your highest number for a 32 bit int is 2^32 except that 0 is still counted as positive so it's actually 2^32-1, now for signed numbers half those numbers are negative. which means we divide the previous number 2^32 by 2, since 32 is an exponent we get 2^31 numbers on each side 0 being positive means the range of an signed 32 bit int is (-2^31, 2^31-1).
Now just comparing ranges:
unsigned 32 bit int: (0, 2^32-1)
signed 32 bit int: (-2^31, 2^32-1)
unsigned 16 bit int: (0, 2^16-1)
signed 16 bit int: (-2^15, 2^15-1)
you should be able to see the pattern here.
to explain the ~0 thing takes a bit more, this has to do with subtraction in binary. it's just adding 1 and flipping all the bits then adding the two numbers together. C does this for you behind the scenes and so do many processors (including the x86 and x64 lines of processors.)
Because of this it's best to store negative numbers as though they are counting down, and in two's complement the added 1 is also hidden. Because 0 is assumed positive thus negative numbers can't have a value for 0, so they automatically have -1 (positive 1 after the bit flip) added to them. when decoding negative numbers we have to account for this.

Resources