I don't get how the computer arrives at 2^31

Discussion in 'C Programming' started by Chad, Dec 13, 2005.

  1. Chad

    Chad Guest

    The question is related to the following lines of code:

    #include <stdio.h>
    #include <math.h>

    int main(void) {

    int a = (int)pow(2.0 ,32.0);
    double b = pow(2.0 , 32.0);

    printf("The value of a is: %u\n",a);
    printf("The value of b is: %0.0f\n",b);
    printf("The value of int is: %d\n", sizeof(int));
    printf("The value of double is: %d\n", sizeof(double));

    return 0;
    }

    The output is:

    $./pw
    The value of a is: 2147483648
    The value of b is: 4294967296
    The value of int is: 4
    The value of double is: 8


    The value of 'a' (on my machine) is 2147483648 or 2^31. Is this anyway
    related to the fact that 1 int in this case is 32 bits? I

    Thanks in advance.
    Chad
    Chad, Dec 13, 2005
    #1
    1. Advertising

  2. Chad

    Guest

    Chad wrote:
    > The question is related to the following lines of code:
    >
    > #include <stdio.h>
    > #include <math.h>
    >
    > int main(void) {
    >
    > int a = (int)pow(2.0 ,32.0);
    > double b = pow(2.0 , 32.0);
    >
    > printf("The value of a is: %u\n",a);
    > printf("The value of b is: %0.0f\n",b);
    > printf("The value of int is: %d\n", sizeof(int));
    > printf("The value of double is: %d\n", sizeof(double));
    >
    > return 0;
    > }
    >
    > The output is:
    >
    > $./pw
    > The value of a is: 2147483648
    > The value of b is: 4294967296
    > The value of int is: 4
    > The value of double is: 8
    >
    >
    > The value of 'a' (on my machine) is 2147483648 or 2^31. Is this anyway
    > related to the fact that 1 int in this case is 32 bits? I
    >


    Try unsigned int. Unless this is a simple test code, for the sizes the
    numbers you are handling I'd recommend long long.
    , Dec 13, 2005
    #2
    1. Advertising

  3. Chad

    Chad Guest

    wrote:
    > Chad wrote:
    > > The question is related to the following lines of code:
    > >
    > > #include <stdio.h>
    > > #include <math.h>
    > >
    > > int main(void) {
    > >
    > > int a = (int)pow(2.0 ,32.0);
    > > double b = pow(2.0 , 32.0);
    > >
    > > printf("The value of a is: %u\n",a);
    > > printf("The value of b is: %0.0f\n",b);
    > > printf("The value of int is: %d\n", sizeof(int));
    > > printf("The value of double is: %d\n", sizeof(double));
    > >
    > > return 0;
    > > }
    > >
    > > The output is:
    > >
    > > $./pw
    > > The value of a is: 2147483648
    > > The value of b is: 4294967296
    > > The value of int is: 4
    > > The value of double is: 8
    > >
    > >
    > > The value of 'a' (on my machine) is 2147483648 or 2^31. Is this anyway
    > > related to the fact that 1 int in this case is 32 bits? I
    > >

    >
    > Try unsigned int. Unless this is a simple test code, for the sizes the
    > numbers you are handling I'd recommend long long.


    Okay, I tried this. I also forgot to use %lu vs %u.

    #include <stdio.h>
    #include <math.h>

    int main(void) {

    unsigned int a = (unsigned int)pow(2.0 ,32.0);
    double b = pow(2.0 , 32.0);

    printf("The value of a is: %lu\n",a);
    printf("The value of b is: %0.0f\n",b);
    printf("The value of int is: %d\n", sizeof(int));
    printf("The value of double is: %d\n", sizeof(double));

    return 0;
    }

    $./pw
    The value of a is: 0
    The value of b is: 4294967296
    The value of int is: 4
    The value of double is: 8

    Now 'a' is zero! Ahhhhhhhhhhhhh........ I'm even more confused.

    Chad
    Chad, Dec 13, 2005
    #3
  4. Chad

    Guest

    It is happening so be cause MSB of the 'a' is used for sign bit. So
    the "4294967296" will be stored in only in the remaining bits of 'a'.
    So the truncation to "2147483648". i.e right shift 4294967296 once that
    will be "2147483648".
    , Dec 13, 2005
    #4
  5. Chad

    Jordan Abel Guest

    On 2005-12-13, Chad <> wrote:
    >
    > wrote:
    >> Chad wrote:
    >> > The question is related to the following lines of code:
    >> >
    >> > #include <stdio.h>
    >> > #include <math.h>
    >> >
    >> > int main(void) {
    >> >
    >> > int a = (int)pow(2.0 ,32.0);
    >> > double b = pow(2.0 , 32.0);
    >> >
    >> > printf("The value of a is: %u\n",a);
    >> > printf("The value of b is: %0.0f\n",b);
    >> > printf("The value of int is: %d\n", sizeof(int));
    >> > printf("The value of double is: %d\n", sizeof(double));
    >> >
    >> > return 0;
    >> > }
    >> >
    >> > The output is:
    >> >
    >> > $./pw
    >> > The value of a is: 2147483648
    >> > The value of b is: 4294967296
    >> > The value of int is: 4
    >> > The value of double is: 8
    >> >
    >> >
    >> > The value of 'a' (on my machine) is 2147483648 or 2^31. Is this anyway
    >> > related to the fact that 1 int in this case is 32 bits? I
    >> >

    >>
    >> Try unsigned int. Unless this is a simple test code, for the sizes the
    >> numbers you are handling I'd recommend long long.

    >
    > Okay, I tried this. I also forgot to use %lu vs %u.


    %lu is for an unsigned long, not for an unsigned int - it should be %u

    > Now 'a' is zero! Ahhhhhhhhhhhhh........ I'm even more confused.


    it's an overflow - neither is big enough to contain 2^32 - the value of
    it when it was an int was actually -2^31.
    Jordan Abel, Dec 13, 2005
    #5
  6. Chad

    arun Guest

    the valuue you got for a is for (2^32) /2.
    this is because 1 int=2 bytes=2*16=32 bits.

    2^32=4294967296. now this is signed integer('cause u used %d"),therfore
    the range is split into two(-ve &+ve)
    i.e 4294967296/2. or (2^32)/2=2^31
    arun, Dec 13, 2005
    #6
  7. Chad

    arun Guest

    this is because u used %lu whereas u declared a as only unsigned int
    not unsigned long int.
    arun, Dec 13, 2005
    #7
  8. Chad

    Guest

    Chad wrote:
    > wrote:
    > > Chad wrote:
    > > > The question is related to the following lines of code:
    > > >
    > > > #include <stdio.h>
    > > > #include <math.h>
    > > >
    > > > int main(void) {
    > > >
    > > > int a = (int)pow(2.0 ,32.0);
    > > > double b = pow(2.0 , 32.0);
    > > >
    > > > printf("The value of a is: %u\n",a);
    > > > printf("The value of b is: %0.0f\n",b);
    > > > printf("The value of int is: %d\n", sizeof(int));
    > > > printf("The value of double is: %d\n", sizeof(double));
    > > >
    > > > return 0;
    > > > }
    > > >
    > > > The output is:
    > > >
    > > > $./pw
    > > > The value of a is: 2147483648
    > > > The value of b is: 4294967296
    > > > The value of int is: 4
    > > > The value of double is: 8
    > > >
    > > >
    > > > The value of 'a' (on my machine) is 2147483648 or 2^31. Is this anyway
    > > > related to the fact that 1 int in this case is 32 bits? I
    > > >

    > >
    > > Try unsigned int. Unless this is a simple test code, for the sizes the
    > > numbers you are handling I'd recommend long long.

    >
    > Okay, I tried this. I also forgot to use %lu vs %u.
    >
    > #include <stdio.h>
    > #include <math.h>
    >
    > int main(void) {
    >
    > unsigned int a = (unsigned int)pow(2.0 ,32.0);
    > double b = pow(2.0 , 32.0);
    >
    > printf("The value of a is: %lu\n",a);
    > printf("The value of b is: %0.0f\n",b);
    > printf("The value of int is: %d\n", sizeof(int));
    > printf("The value of double is: %d\n", sizeof(double));
    >
    > return 0;
    > }
    >
    > $./pw
    > The value of a is: 0
    > The value of b is: 4294967296
    > The value of int is: 4
    > The value of double is: 8
    >
    > Now 'a' is zero! Ahhhhhhhhhhhhh........ I'm even more confused.
    >


    Ahh... that just means that on your platform an int is 32 bits:

    4294967296 = (binary) 100000000000000000000000000000000
    which is 33 bits. So when your computer does its calculation, it will
    only store 32 of those 33 bits, resulting in:
    (binary, first 1 chopped off) 00000000000000000000000000000000
    which is zero.

    The largest 32bit number is (2^32)-1. Of course, this number can't be
    calculated on a 32bit CPU (unless using long long of course) since the
    2^32 part will simply result in a zero.

    Another interesting experiment to see if your CPU uses 2s complement
    arithmetic:

    unsigned int a = (int) -1;
    printf("The value of a is: %u\n",a);

    Anyway, all this is probably a little OT. And my code above is not
    strictly portable. The best advice if you really want to be handling
    large numbers is to use long long which will give you at least 64 bits.
    , Dec 13, 2005
    #8
  9. Chad

    Guest

    wrote:
    > Chad wrote:
    > > wrote:
    > > > Chad wrote:
    > > > > The question is related to the following lines of code:
    > > > > <snip>
    > > > > The output is:
    > > > >
    > > > > $./pw
    > > > > The value of a is: 2147483648
    > > > > The value of b is: 4294967296
    > > > > The value of int is: 4
    > > > > The value of double is: 8
    > > > >
    > > > > The value of 'a' (on my machine) is 2147483648 or 2^31. Is this anyway
    > > > > related to the fact that 1 int in this case is 32 bits? I
    > > >
    > > > Try unsigned int. Unless this is a simple test code, for the sizes the
    > > > numbers you are handling I'd recommend long long.

    > >
    > > Okay, I tried this. I also forgot to use %lu vs %u.
    > > <snip>
    > > $./pw
    > > The value of a is: 0
    > > The value of b is: 4294967296
    > > The value of int is: 4
    > > The value of double is: 8
    > >
    > > Now 'a' is zero! Ahhhhhhhhhhhhh........ I'm even more confused.
    > >

    >
    > Ahh... that just means that on your platform an int is 32 bits:
    >
    > 4294967296 = (binary) 100000000000000000000000000000000
    > which is 33 bits. So when your computer does its calculation, it will
    > only store 32 of those 33 bits, resulting in:
    > (binary, first 1 chopped off) 00000000000000000000000000000000
    > which is zero.
    >
    > The largest 32bit number is (2^32)-1. Of course, this number can't be
    > calculated on a 32bit CPU (unless using long long of course) since the
    > 2^32 part will simply result in a zero.
    >
    > Another interesting experiment to see if your CPU uses 2s complement
    > arithmetic:
    >
    > unsigned int a = (int) -1;
    > printf("The value of a is: %u\n",a);
    >


    Forgot to mention, if you get (2^32)-1 which is 4294967295 then your
    CPU uses 2's complement math. If instead you get 2^31 which is
    2147483648 then your CPU uses a simple integer with sign bit.
    , Dec 13, 2005
    #9
  10. Chad

    Chad Guest

    > Ahh... that just means that on your platform an int is 32 bits:
    >
    > 4294967296 = (binary) 100000000000000000000000000000000
    > which is 33 bits. So when your computer does its calculation, it will
    > only store 32 of those 33 bits, resulting in:
    > (binary, first 1 chopped off) 00000000000000000000000000000000
    > which is zero.
    >
    > The largest 32bit number is (2^32)-1. Of course, this number can't be
    > calculated on a 32bit CPU (unless using long long of course) since the
    > 2^32 part will simply result in a zero.
    >
    > Another interesting experiment to see if your CPU uses 2s complement
    > arithmetic:
    >
    > unsigned int a = (int) -1;
    > printf("The value of a is: %u\n",a);
    >
    > Anyway, all this is probably a little OT. And my code above is not
    > strictly portable. The best advice if you really want to be handling
    > large numbers is to use long long which will give you at least 64 bits.


    Speaking of long long, I tried this:

    include <stdio.h>
    #include <math.h>

    int main(void) {

    int a = (int)pow(2.0 ,32.0);
    double b = pow(2.0 , 32.0);
    long long c = 4294967296;

    printf("The value of a is: %u\n",a);
    printf("The value of b is: %0.0f\n",b);
    printf("The value of int is: %d\n", sizeof(int));
    printf("The value of double is: %d\n", sizeof(double));

    printf("The value of c is: %llu\n",c>>1);
    }

    The output is:
    $gcc pw.c -o pw -lm
    pw.c: In function `main':
    pw.c:8: warning: integer constant is too large for "long" type
    $./pw
    The value of a is: 2147483648
    The value of b is: 4294967296
    The value of int is: 4
    The value of double is: 8
    The value of c is: 2147483648
    $


    Interesting.

    Chad
    Chad, Dec 13, 2005
    #10
  11. Chad

    Chad Guest

    Chad wrote:
    > > Ahh... that just means that on your platform an int is 32 bits:
    > >
    > > 4294967296 = (binary) 100000000000000000000000000000000
    > > which is 33 bits. So when your computer does its calculation, it will
    > > only store 32 of those 33 bits, resulting in:
    > > (binary, first 1 chopped off) 00000000000000000000000000000000
    > > which is zero.
    > >
    > > The largest 32bit number is (2^32)-1. Of course, this number can't be
    > > calculated on a 32bit CPU (unless using long long of course) since the
    > > 2^32 part will simply result in a zero.
    > >
    > > Another interesting experiment to see if your CPU uses 2s complement
    > > arithmetic:
    > >
    > > unsigned int a = (int) -1;
    > > printf("The value of a is: %u\n",a);
    > >
    > > Anyway, all this is probably a little OT. And my code above is not
    > > strictly portable. The best advice if you really want to be handling
    > > large numbers is to use long long which will give you at least 64 bits.

    >
    > Speaking of long long, I tried this:
    >
    > include <stdio.h>
    > #include <math.h>
    >
    > int main(void) {
    >
    > int a = (int)pow(2.0 ,32.0);
    > double b = pow(2.0 , 32.0);
    > long long c = 4294967296;
    >
    > printf("The value of a is: %u\n",a);
    > printf("The value of b is: %0.0f\n",b);
    > printf("The value of int is: %d\n", sizeof(int));
    > printf("The value of double is: %d\n", sizeof(double));
    >
    > printf("The value of c is: %llu\n",c>>1);
    > }
    >
    > The output is:
    > $gcc pw.c -o pw -lm
    > pw.c: In function `main':
    > pw.c:8: warning: integer constant is too large for "long" type
    > $./pw
    > The value of a is: 2147483648
    > The value of b is: 4294967296
    > The value of int is: 4
    > The value of double is: 8
    > The value of c is: 2147483648
    > $
    >
    >
    > Interesting.
    >
    > Chad


    Before I forget. In regards to using %lu vs %u, I need day or two to
    let in sink in.

    Chad
    Chad, Dec 13, 2005
    #11
  12. Chad

    Old Wolf Guest

    Chad wrote:

    > The question is related to the following lines of code:
    >
    > #include <stdio.h>
    > #include <math.h>
    >
    > int main(void) {
    >
    > int a = (int)pow(2.0 ,32.0);


    Undefined behaviour -- the return value from pow() is greater
    than INT_MAX .

    > printf("The value of a is: %u\n",a);


    Undefined behaviour -- %u is for unsigned ints.
    Also, %llu or %Lu is for unsigned long longs
    (in another message you used it for a signed long long).

    > The value of a is: 2147483648


    That isn't even a valid int value.
    Old Wolf, Dec 13, 2005
    #12
  13. Chad

    Jordan Abel Guest

    On 2005-12-13, Old Wolf <> wrote:
    int a /* = INT_MIN */;
    >> printf("The value of a is: %u\n",a);

    >
    > Undefined behaviour -- %u is for unsigned ints.


    it's not clear that it's undefined - an unsigned int and a signed int
    have the same size, and it's not clear that int can have any valid
    representations that are trap representations for unsigned.

    > Also, %llu


    yes.

    > or %Lu


    no.

    > is for unsigned long longs
    Jordan Abel, Dec 13, 2005
    #13
  14. Chad

    pete Guest

    Jordan Abel wrote:
    >
    > On 2005-12-13, Old Wolf <> wrote:
    > int a /* = INT_MIN */;
    > >> printf("The value of a is: %u\n",a);

    > >
    > > Undefined behaviour -- %u is for unsigned ints.

    >
    > it's not clear that it's undefined -


    It's undefined because the standard says that
    %u is for unsigned ints.
    You don't need to be able to think of a failure mechanism,
    for undefined code to be undefined.
    Undefined behavior makes learning the language simpler.

    For the case of
    i = 0;
    i = i++;
    it makes sense to me that the final value of i
    could be either 1 or 2,
    but that code is not unspecified, it's undefined.

    --
    pete
    pete, Dec 13, 2005
    #14
  15. Chad

    Skarmander Guest

    Jordan Abel wrote:
    > On 2005-12-13, Old Wolf <> wrote:
    > int a /* = INT_MIN */;
    >>> printf("The value of a is: %u\n",a);

    >> Undefined behaviour -- %u is for unsigned ints.

    >
    > it's not clear that it's undefined - an unsigned int and a signed int
    > have the same size, and it's not clear that int can have any valid
    > representations that are trap representations for unsigned.
    >

    No, this is pretty clear. The type of the argument required for a "%u"
    format specifier is "unsigned int". From 7.9.16.1:

    "If any argument is not the correct type for the corresponding conversion
    specification, the behavior is undefined."

    While, for the reasons you mention, most if not all platforms will treat
    this as expected, the standard does not explicitly allow it. "int" is not
    the correct type.

    S.
    Skarmander, Dec 14, 2005
    #15
  16. Chad

    Jordan Abel Guest

    On 2005-12-13, pete <> wrote:
    > Jordan Abel wrote:
    >>
    >> On 2005-12-13, Old Wolf <> wrote:
    >> int a /* = INT_MIN */;
    >> >> printf("The value of a is: %u\n",a);
    >> >
    >> > Undefined behaviour -- %u is for unsigned ints.

    >>
    >> it's not clear that it's undefined -

    >
    > It's undefined because the standard says that %u is for unsigned ints.


    Things are only undefined because the standard says that they are
    undefined, not for any other reason. As it happens, this is in fact the
    case, 7.19.6.1p9 "If any argument is not the correct type for the
    corresponding conversion specification, the behavior is undefined".

    However, if we assume that printf is a variadic function implemented
    along the lines of the stdarg.h macros, we see 7.15.1.1p2 "...except for
    the following cases: - one type is a signed integer type, the other type
    is the corresponding unsigned integer type, and the value is
    representable in both types" - In this case, the value is not, but "%u
    is for unsigned ints" as a blanket statement would seem to be incorrect.
    comp.std.c added - do the signed/unsigned exception, and the char*/void*
    one, to va_arg type rules also apply to printf?

    Incidentally, my copy of some c89 draft says that %u takes an int and
    converts it to unsigned. c99 changes this to take an unsigned int. There
    are several possibilities: Perhaps they screwed up (but the c99
    rationale does not comment on this), or they thought the difference was
    insignificant enough not to matter.

    > You don't need to be able to think of a failure mechanism, for
    > undefined code to be undefined. Undefined behavior makes learning the
    > language simpler.
    Jordan Abel, Dec 14, 2005
    #16
  17. Chad

    Ben Pfaff Guest

    Jordan Abel <> writes:

    > Things are only undefined because the standard says that they are
    > undefined, not for any other reason.


    That is not true. Here is the definition of undefined behavior:

    1 undefined behavior
    behavior, upon use of a nonportable or erroneous program
    construct or of erroneous data, for which this International
    Standard imposes no requirements

    Anything that the Standard does not define is undefined.
    --
    Bite me! said C.
    Ben Pfaff, Dec 14, 2005
    #17
  18. Chad

    Jordan Abel Guest

    On 2005-12-14, Ben Pfaff <> wrote:
    > Jordan Abel <> writes:
    >
    >> Things are only undefined because the standard says that they are
    >> undefined, not for any other reason.

    >
    > That is not true. Here is the definition of undefined behavior:
    >
    > 1 undefined behavior
    > behavior, upon use of a nonportable or erroneous program
    > construct or of erroneous data, for which this International
    > Standard imposes no requirements
    >
    > Anything that the Standard does not define is undefined.


    Then why does it go to such pains to declare things to be "undefined
    behavior"? the word undefined appears 182 times in c99, and there are
    191 points in J.2 [yes, i counted them. by hand. these things should
    really be numbered - at least they contain pointers to the sections they
    refer to.]

    Name one instance of undefined behavior that is not explicitly declared
    undefined by the standard?

    Alternative hypothesis: the definition you quoted is meant to explain
    that when they [explicitly] say something is undefined, that _means_ no
    requirements can be inferred from other sections to apply to that
    behavior.
    Jordan Abel, Dec 14, 2005
    #18
  19. Chad

    Ben Pfaff Guest

    Jordan Abel <> writes:

    > On 2005-12-14, Ben Pfaff <> wrote:
    >> Anything that the Standard does not define is undefined.

    >
    > Then why does it go to such pains to declare things to be "undefined
    > behavior"? the word undefined appears 182 times in c99, and there are
    > 191 points in J.2 [yes, i counted them. by hand. these things should
    > really be numbered - at least they contain pointers to the sections they
    > refer to.]


    In my opinion, it is important that we have clearly delineated
    areas of doubt and uncertainty, where possible.

    > Name one instance of undefined behavior that is not explicitly declared
    > undefined by the standard?
    >
    > Alternative hypothesis: the definition you quoted is meant to explain
    > that when they [explicitly] say something is undefined, that _means_ no
    > requirements can be inferred from other sections to apply to that
    > behavior.


    There is an easy answer to this question. There are committee
    members in comp.std.c. They can answer "yea" or "nay", should
    they deign. Based on historical discussion in comp.lang.c, I
    have one opinion. You have another.
    --
    "What is appropriate for the master is not appropriate for the novice.
    You must understand the Tao before transcending structure."
    --The Tao of Programming
    Ben Pfaff, Dec 14, 2005
    #19
  20. Chad

    pete Guest

    Jordan Abel wrote:

    > Incidentally, my copy of some c89 draft says that %u takes an int and
    > converts it to unsigned. c99 changes this to take an unsigned int.


    ISO/IEC 9899: 1990

    7.9.6.1 The fprintf function

    o, u, x, X The unsigned int argument is converted to

    --
    pete
    pete, Dec 14, 2005
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. A. M. G. Solo
    Replies:
    0
    Views:
    525
    A. M. G. Solo
    Jan 13, 2006
  2. Vincent Courcelle
    Replies:
    0
    Views:
    405
    Vincent Courcelle
    May 25, 2006
  3. A. M. G. Solo
    Replies:
    0
    Views:
    776
    A. M. G. Solo
    Jun 8, 2006
  4. Replies:
    0
    Views:
    340
  5. jalkadir
    Replies:
    2
    Views:
    366
Loading...

Share This Page