2

Why is it that when I run the C code

float x = 4.2
int y = 0
y = x*100
printf("%i\n", y);

I get 419 back? Shouldn't it be 420? This has me stumped.

Fearless
  • 65
  • 1
  • 7

4 Answers4

3

To illustrate, look at the intermediate values:

int main()
{
    float x = 4.2;
    int y;

    printf("x = %f\n", x);
    printf("x * 100 = %f\n", x * 100);
    y = x * 100;

    printf("y = %i\n", y);

    return 0;
}

x = 4.200000            // Original x
x * 100 = 419.999981    // Floating point multiplication precision
y = 419                 // Assign to int truncates

Per @Lutzi's excellent suggestion, this is more clearly illustrated if we print all the float values with precision that is higher than they represent:

...
printf("x = %.20f\n", x);
printf("x * 100 = %.20f\n", x * 100);
...

And then you can see that the value assigned to x isn't perfectly precise to start with:

x = 4.19999980926513671875
x * 100 = 419.99998092651367187500
y = 419
lurker
  • 56,987
  • 9
  • 69
  • 103
1

A floating point number is stored as an approximate value - not the exact floating point value. It has a representation due to which the result gets truncated when you convert it into an integer. You can see more information about the representation here.

This is an example representation of a single precision floating point number :

enter image description here

Dinesh
  • 2,194
  • 3
  • 30
  • 52
0

4.2 is not in the finite number space of a float, so the system uses the closest possible approximation, which is slightly below 4.2. If you now multiply this with 100 (which is an exact float), you get 419.99something. printf()ing this with %i performs not rounding, but truncation - so you get 419.

Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92
  • The “printf()ing this with %i performs not rounding, but truncation” part of this answer is wrong. The function `printf` is variadic. It performs no conversion on its arguments after the first one. The **assignment** `y=` converts `419.99something` into `419`. Passing a floating-point number to `printf("%i` would be undefined behavior. – Pascal Cuoq Mar 27 '14 at 08:48
  • @PascalCuoq - That is exactly what I was saying: you take 419.99something and printf('%i') it ... which ofcourse implies a cast. English is not my first language, but I would have thought that to be unambitious – Eugen Rieck Mar 27 '14 at 10:13
0

float isn't large enough to store 4.2 precisely. If you print x with enough precision you'll probably see it come out as 4.19999995 or so. Multiplying by 100 yields 419.999995 and the integer assignment truncates (rounds down). It should work if you make x a double.

  • 1
    A `double` cannot represent `4.2` exactly any more than a `float` can. It may work by “luck” with a `double` type if the `double` nearest to 4.2 is above 4.2 instead of being below it, but without looking, it is in first approximation a 50-50 chance. – Pascal Cuoq Mar 27 '14 at 09:23
  • 1
    More precisely, the decimal representation of the stored value for `4.2` is `4.19999980926513671875`. And yes, your guess is right, in double precision, the stored value representing `4.2`is `4.20000000000000017763568394002504646778106689453125`. – Lutz Lehmann Mar 27 '14 at 10:43