Thread: Negative numbers in C

  1. #1
    Registered User
    Join Date
    Feb 2008
    Posts
    43

    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.

    Thank you.

  2. #2
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    But how is it possible know that 1111 is not a 15 and it is -1 ...
    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).

  3. #3
    DESTINY BEN10's Avatar
    Join Date
    Jul 2008
    Location
    in front of my computer
    Posts
    804
    Quote Originally Posted by BlaX View Post
    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.
    HOPE YOU UNDERSTAND.......

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


    PC specifications- 512MB RAM, Windows XP sp3, 2.79 GHz pentium D.
    IDE- Microsoft Visual Studio 2008 Express Edition

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by cyberfish View Post
    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.

    *or (even more confusing) the reverse of the total value +1
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by MK27 View Post
    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.

  6. #6
    Registered User
    Join Date
    Feb 2008
    Posts
    43

    If you use it as a signed integer, it's -1, otherwise it's 15.
    Let's say you have a variable int x=-1

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

    usually call the most-significant-bit (the one on the left) the "sign bit". If it's 1, the number is negative, vice versa.
    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.
    even the msb won't let us now if 11111111 is 255 or -1 .

    If it is signed, it will be "sign-extended" (all upper 24 bits set to the MSB of the char).
    if we're talking about a char the maximum bits lets say is 8 ...
    Thought I didn't understand what u meant by saying all the upper bits are set to the MSB.

  7. #7
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    it is stored as 11111111 in memory ... if we add 1 to x ... how can we determine if the answer is 0 or 256 ?
    In this case it will overflow and give you 0 in both cases (a char stores up to 255).

    However, generally, both "cases" will also have the same binary representation. That's the beauty of 2's complement.

    For example, if you have 10000001, which can be either -127 or 129, if you add 3 to it, you get -124 (10000100) or 132 (10000100). Same binary representation!

    even the msb won't let us now if 11111111 is 255 or -1 .
    It lets you know the sign of the number IF YOU CHOOSE TO INTERPRET IT AS SIGNED.

    if we're talking about a char the maximum bits lets say is 8 ...
    Thought I didn't understand what u meant by saying all the upper bits are set to the MSB.
    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).

  8. #8
    Registered User
    Join Date
    Feb 2008
    Posts
    43

    For example, if you have 10000001, which can be either -127 or 129, if you add 3 to it, you get -124 (10000100) or 132 (10000100). Same binary representation!
    Let's say that number is stored in a signed char variable x and we want to print it.

    Code:
    printf("%d",x);
    should i get -124 or 132 ?

    what makes it be -124 or 132 ... knowing that it is a signed char

    It lets you know the sign of the number IF YOU CHOOSE TO INTERPRET IT AS SIGNED.
    Let's say we declared the variable as a signed char... which is signed.
    But in what way will 10000100 be -124 or 132.

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by BlaX
    what makes it be -124 or 132 ... knowing that it is a signed char
    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.

    Quote Originally Posted by BlaX
    should i get -124 or 132 ?
    Thus the answer is obviously -127 + 3 = -124.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    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.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    should i get -124 or 132 ?

    what makes it be -124 or 132 ... knowing that it is a signed char
    The fact that you defined it to be (by default or explicitly) signed or unsigned.

    Let's say we declared the variable as a signed char... which is signed.
    But in what way will 10000100 be -124 or 132.
    If you interpret it as signed, it has to be -124. The MSB gives you the sign (negative) in this case, and the 2's complement gives you the magnitude (124).

  11. #11
    DESTINY BEN10's Avatar
    Join Date
    Jul 2008
    Location
    in front of my computer
    Posts
    804
    Quote Originally Posted by BlaX View Post
    Let's say you have a variable int x=-1

    => 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).
    HOPE YOU UNDERSTAND.......

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


    PC specifications- 512MB RAM, Windows XP sp3, 2.79 GHz pentium D.
    IDE- Microsoft Visual Studio 2008 Express Edition

  12. #12
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> 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.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  13. #13
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by BlaX View Post
    Let's say that number is stored in a signed char variable x and we want to print it.

    Code:
    printf("%d",x);
    should i get -124 or 132 ?

    what makes it be -124 or 132 ... knowing that it is a signed char



    Let's say we declared the variable as a signed char... which is signed.
    But in what way will 10000100 be -124 or 132.
    Since you passed %d to printf(), and %d means a signed integer, it would interpret x as a negative number. If you passed %u instead, then it should interpret it as an unsigned integer.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  14. #14
    Registered User
    Join Date
    Feb 2008
    Posts
    43
    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

  15. #15
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by BlaX View Post
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Writing unique numbers to an array
    By yardy in forum C Programming
    Replies: 6
    Last Post: 12-27-2006, 09:15 PM
  2. Adding Line numbers in Word
    By Mister C in forum A Brief History of Cprogramming.com
    Replies: 24
    Last Post: 06-24-2004, 08:45 PM
  3. the definition of a mathematical "average" or "mean"
    By DavidP in forum A Brief History of Cprogramming.com
    Replies: 7
    Last Post: 12-03-2002, 11:15 AM
  4. Line Numbers in VI and/or Visual C++ :: C++
    By kuphryn in forum C++ Programming
    Replies: 2
    Last Post: 02-10-2002, 10:54 PM
  5. A (complex) question on numbers
    By Unregistered in forum C++ Programming
    Replies: 8
    Last Post: 02-03-2002, 06:38 PM