Negative numbers in C

This is a discussion on Negative numbers in C within the C Programming forums, part of the General Programming Boards category; hey everyone. i had this question going in my mind about negative numbers and how they are stored in memory.i ...

Negative numbers in C

hey everyone. i had this question going in my mind about negative numbers and how they are stored in memory.i have read that in order to obtain the negative of a number , the 2's compliment is taken and added a 1 to it.

for example if we have a variable char that has number 1 in it.
=> 0001

to get -1 => 1110 (2's..) =>add 1=> 1111

But how is it possible know that 1111 is not a 15 and it is -1 ...

As for my 2nd question .. if a type conversion should occur from a char to an int during some operation it would b machine dependent to make the char an unsigned int (by adding zeros at the back) or by making it signed. My question is , how will it be signed i mean what operation would it undergo to achieve it.

It can actually be either 15 or -1, depending on interpretation. "Data is what you define it to be."

If you use it as a signed integer, it's -1, otherwise it's 15.

Oh and, in modern computers, bits are stored in groups of 8 (called bytes). So, if you are using a char to store it, 1 would be 00000001, and its 2's complement would be 11111111. We usually call the most-significant-bit (the one on the left) the "sign bit". If it's 1, the number is negative, vice versa.

To the computer its just a sequence of bits. Whether they "are" -1 or 255 would depend on how you use them.

As for my 2nd question .. if a type conversion should occur from a char to an int during some operation it would b machine dependent to make the char an unsigned int (by adding zeros at the back) or by making it signed. My question is , how will it be signed i mean what operation would it undergo to achieve it.

That would depend on whether char is signed or unsigned (which is implementation-defined). If it is unsigned, it will be zero-extended to make the int (all upper 24 bits set to 0). If it is signed, it will be "sign-extended" (all upper 24 bits set to the MSB of the char).

hey everyone. i had this question going in my mind about negative numbers and how they are stored in memory.i have read that in order to obtain the negative of a number , the 2's compliment is taken and added a 1 to it.

for example if we have a variable char that has number 1 in it.
=> 0001

to get -1 => 1110 (2's..) =>add 1=> 1111

But how is it possible know that 1111 is not a 15 and it is -1 ...

Thank you.

Negative numbers are stored as 2's complement of its positive part. By the way after changing 0 to 1 and vice versa you dont get the 2's complement but the 1's complement, so in your example 1110 is the 1's complement and after adding 1 to the 1's complement you get a 2's complement.
1111 will be a negative number coz the MSB is used to know whether the number is actually negative or a positive. If the MSB is 1 it's terated as negative and if 0 it's treated as positive. Also as cyberfish pointed out the char is taken as 8bits in most of the compilers today.

By associating with wise people you will become wise yourselfIt's fine to celebrate success but it is more important to heed the lessons of failureWe've got to put a lot of money into changing behavior

Oh and, in modern computers, bits are stored in groups of 8 (called bytes). So, if you are using a char to store it, 1 would be 00000001, and its 2's complement would be 11111111. We usually call the most-significant-bit (the one on the left) the "sign bit".

And the lowest negative number, -128, is 10000000. The reason 1111 signed would be -1 is because the most significant bit (the sign bit) is set; 00001111 would still be 15, but that is contrasting an eight bit number with a four bit one. With a signed type, all numbers with the MSB set are negative, all numbers without the MSB set are positive.

The only confusing part about it is that the value of the actual "value bits" (0-7) is reversed with negative numbers*; why -1 should be 11111111 instead of 10000001 and -128 10000000 instead of 11111111 I don't know -- maybe it makes arithmetic simpler for the processor.

The only confusing part about it is that the value of the actual "value bits" (0-7) is reversed with negative numbers*; why -1 should be 11111111 instead of 10000001 and -128 10000000 instead of 11111111 I don't know -- maybe it makes arithmetic simpler for the processor.

I remember when they used to teach people "subtraction with borrowing" in school.

Well, assume 8 bit bytes with a 2's complement binary representation. So, the range for a signed char is [-128,127]. Since 129 is out of the range, the initial value must be -127. This determining of the range would be based on what has been told to you earlier in this thread.

I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.

=> it is stored as 11111111 in memory ... if we add 1 to x ... how can we determine if the answer is 0 or 256 ?

even the msb won't let us now if 11111111 is 255 or -1 .

If you add 1 to -1 obviously you'll get a 0. And this addition also results in the carry bit being set i.e carry now becomes 1. But the actual magnitude will be the 8bits starting from LSB.
If you are taking char to be signed then 11111111 will be -1 coz signed char has a range of -128 to 127 and this way the MSB decides it that the number is negative but on the other hand if you take char to be unsigned then it'll obviously be 255 coz unsigned has a range of 0 to 255 and in case of unsigned the MSB is doesn't signify anything(coz it's already without a sign).

By associating with wise people you will become wise yourselfIt's fine to celebrate success but it is more important to heed the lessons of failureWe've got to put a lot of money into changing behavior

>> i have read that in order to obtain the negative of a number , the 2's compliment is taken and added a 1 to it

The terminology is just a bit off there. To obtain the twos-compliment representation of a number you find its ones-compliment (negate each bit) and then add one.

>> why -1 should be 11111111 instead of 10000001 and -128 10000000 instead of 11111111 I don't know -- maybe it makes arithmetic simpler for the processor.

Right. The advantage of using twos-compliment is that it simplifies hardware logic in that it allows subtraction to be implemented as addition, and it works identically for signed and unsigned interpretations. For example, let's say we're dealing with 8-bit signed quantities, and we want to perform the operation 13 - 6:

Code:

0000 1101 (13)
- 0000 0110 (6)

After obtaining the twos-compliment of 6 we can now just add the two numbers together:

Code:

0000 1101 (13)
+ 1111 1010 (-6)

The initial result is:

Code:

1 0000 0111

But since we're working with 8-bit numbers the carry is discarded and the final result is 0000 0111 (7).

Notice that had the subtrahend been -6 (1111 1010) the same procedure would have produced 0001 0011 (19), eg: 13 - (-6) == 13 + 6 == 19.

Also note that had the first problem been 6 - 13, the logic is still the same:

Code:

0000 0110 (6)
- 0000 1101 (13)

After twos-compliment:

Code:

0000 0110 (6)
+ 1111 0011 (-13)

The result, of course, is 1111 1001 (-7). Naturally, if these had been unsigned 8-bit quantities the interpretation of 1111 1001 would be 249.

thank you all for your answers. i really understood everything you said. Appreciated.

Say you want to extend 10011001 to 16 bits.

Zero extension -
00000000 10011001
The upper bits are simply set to 0.

Sign extension -
11111111 10011001
The upper bits are set to the MSB of the original byte (the leftmost 1).

I was wondering .. where do these conversions take place ? im sure they won't be at the memory level because that will cause overriding and overflows in memory ... is it in the registers ?
Anyway why should they be converted afterall?Whats the purpose behind it.
Thank you

thank you all for your answers. i really understood everything you said. Appreciated.

I was wondering .. where do these conversions take place ? im sure they won't be at the memory level because that will cause overriding and overflows in memory ... is it in the registers ?
Anyway why should they be converted afterall?Whats the purpose behind it.
Thank you

If you want to operate on a number (add to it, subtract, multiply, etc.) generally that number has to be put in a register first, and registers nowadays are longer than one byte.