1

I wrote the following code in C:

int main(){
  int i;
  double x;
  for (i = 0, x = -1; x<= 1; x = x + 0.025)
    printf("X = %.3f\n",x);
  return 0;
}

I don't know why, but the last line is "X = 0.975".

Can someone explain me why does the loop stop at this point and not precede one more step to X = 1?

Asaf Kahlon
  • 104
  • 1
  • 9
  • Actually comparison of floating point number is made with some delta (we java prodrammers often do so), so try: int main(int argc, char** argv) { int i; double x; for (i = 0, x = -1; x - 1.00 <= 0.001; x = x + 0.025) printf("X = %.3f\n",x); return 0; } – Alexander Arutinyants Dec 23 '14 at 08:10

1 Answers1

4

Welcome to the wonderful world of floating point, where nothing is as it seems :-)

Most likely the final value of x is something like 1.0000000042 which, despite the fact it would be printed as 1.000, is still compared as being greater than one.

If you modify your code thus, you'll see what I mean:

#include <stdio.h>
int main (void) {
    int i;
    double x;
    for (i = 0, x = -1; x <= 1; x = x + 0.025)
        printf("X = %.3f (%.20f)\n", x, x);
    printf("X = %.3f (%.20f)\n", x, x);
    return 0;
}

The lines of that output are:

X = -1.000 (-1.00000000000000000000)
X = -0.975 (-0.97499999999999997780)
X = -0.950 (-0.94999999999999995559)
X = -0.925 (-0.92499999999999993339)
X = -0.900 (-0.89999999999999991118)
: : : : :
X = 0.900 (0.90000000000000113243)
X = 0.925 (0.92500000000000115463)
X = 0.950 (0.95000000000000117684)
X = 0.975 (0.97500000000000119904)
X = 1.000 (1.00000000000000111022)

and you can see the inaccuracies creeping in pretty quickly.

You may also want to print out the value 0.025 with that %.20f format specifier - you'll see something like:

0.02500000000000000139

because 25/1000 (or 1/40) is one of those numbers which cannot be represented exactly in IEEE754 double precision.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • I wonder why the compiler doesn't replace the condition `x<=1` with `x<=1.0000000042`. – barak manos Dec 23 '14 at 08:09
  • 2
    @barak, because `1` _can_ be represented exactly. It's the cumulative errors of adding the inexact `0.025` that's causing the issue. Try it with steps that can be represented exactly (like `1/16` (0.0625)) and it works fine. – paxdiablo Dec 23 '14 at 08:14