views:

216

answers:

5
int main(void){
    float x =1;
    float y =2;
    while (x<y){
     x = x +1 ;
     y = y +1;
}
    printf("x is %d\n", x);
    printf("y is %d\n", y);
}

I would expect x and y to increase to the point we run out of bits, but it seems like x and y is alway 0 in this case...

+3  A: 

One thing: You should not use %d in printf for floats, use %f, %e or %g instead

dalle
+12  A: 

%d is for an integer.

http://www.cplusplus.com/reference/clibrary/cstdio/printf/

Use %f for floats:

printf("x is %f\n", x);
printf("y is %f\n", y);
JeffH
+13  A: 

As others have stated, you should be using the %f format to print floats, not %d, which is for integers. There is also %e, which prints the float in scientific notation instead of fixed notation, and there's also %g, which prints it in either scientific or fixed, whichever is shorter.

The reason why it prints as 0 is because float arguments automatically get converted to doubles when passed as arguments to variadic functions (that is, functions which take an unspecified number of arguments) such as printf(). The representations of the numbers 2 and 3 (the values of x and y) as doubles are 0x4000000000000000 and 0x4008000000000000 respectively, as calculated by the IEEE-754 Floating-Point Conversion calculator.

On little-endian machines (e.g. anything x86-based), the %d modifier grabs the next 4 bytes off the stack and interprets them as an integer. So, when you pass the float 2, it gets converted to a double as 0x4000000000000000, which in little-endian is 00 00 00 00 00 00 00 40. The first four bytes make the integer 0, so that's what is printed out.

Note that if you printed both numbers in one statement instead of two, you would get a more surprising result:

printf("x=%d y=%d\n", x, y);
// Output: x=0 y=1073741824

Most compilers can warn you about these types of errors if you set the warning level high enough. With GCC, you should compile with the -Wformat option (or -Wall, which includes -Wformat), and it will warn you when you try to print a float with %d by accident.

Adam Rosenfield
Exactly right, except that x and y should both be 2^24 when the printf statements are reached (2^24 + 1 rounds to 2^24 in single precision). As a double, 2^24 is 0x4170000000000000, so the rest of your analysis carries through just fine.
Stephen Canon
(And, as always, all bets are off if you're using a compiler that chooses to do some or all float evaluation in 80-bit extended.)
Stephen Canon
This is a good answer!.
slashmais
Err, right -- I misread the `while()` as an `if()`.
Adam Rosenfield
+1  A: 

I would expect x and y to increase to the point we run out of bits

No, rather the loop will stop when you run out of precision. I believe that at some point the number will be large enough that an increment of 1.0f is too small to be represented, and x will become equal to y.

When you fix your output formatting I am guessing that you will see that to be the case.

Clifford
Specifically: 2^24, if your compiler actually does all the float evaluation in single precision.
Stephen Canon
A: 

%d is for integer, use %f.

You will run out of bits but not exactly like an integer, you will overflow the exponent eventually and that should cause an exception, although you probably wont know that. I forget if that leads to a nan or an infinity. Which makes the less than get intereating. I wonder why the while loop doesnt run forever.

dwelch