0.00001 Increment

Viewed 136

I’m a beginner to C and I’m trying to do the 0.00001 increment in a While Loop. For example, double t = 0.00001 and I want the the loop to run every time by increment of 0.00001 ,which the second time would be 0.00002 and so on. Can anyone please help?

This is a part of my code that I’m debugging. I’m trying to run simulation until v becomes a negative value. And every time the While Loop is true and repeat I want to it to add an increment of 0.00001

    t = 0.00001; 
    f = fMid;  
    v = v0; 
    x = 0;  

    // 10.2 Calculate the simulated stopping distance
    while( v >= 0)
    { 
     a = - f - (C_d)*(v*v); 

     // Calculate the new position 
     x_new = x + (v*t);  

     // Calculate the new velocity
     v_new = v + (a*t);

     x = x_new;
     v = v_new;

     ++t;
    }
2 Answers

Since the floating point arithmetic is not precise (see Is floating point math broken? ) a "naive" approach such as:

double t = 0.0;
while (t < N) {   // Or your specific condition here
    t += 0.00001;
}

might not be working having the possible issues:

  1. At each iteration the error caused by the imprecise calculation will accumulate and will become larger the longer the loop is.
  2. At some point the numbers t and t+0.00001 might become equal because the double representation might not be able to distinguish between them.

To prevent (2) and to minimize the effect of (1) one can use an integer counter instead and recalculate the value of t based on it at each loop:

unsigned int ii = 0;
double t;
while (ii < N) {   // Or your specific condition here
    t = ii * 0.00001;
    ii ++;
}

If you take the intuitive approach and simply increment t thus:

double t = 0 ;

while( t < target )
{
    t += 0.00001 ;
}

You will find that the accumulated error caused by incrementing a binary floating point by a decimal real value (necessarily imprecisely converted to binary) soon causes the t to no longer be an accurate multiple of 0.00001. To prevent that you would do better to use:

double t = 0 ;
int i = 0 ;

while( t < target )
{
    t = i * 0.00001 ;
    i++ ;
}

For example consider:

#include <stdio.h>

int main()
{
    double target = 20000.0 ;
    int i = 0 ;
    double t = 0 ;
    while( t < target )
    {
        t += 0.00001 ;
        i++ ;
    }
    printf( "%d : %f\n", i, t ) ;

    t = 0 ;
    i = 0 ;
    while( t < target )
    {
        t = i * 0.00001 ;
        i++ ;
    }
    printf( "%d : %f\n", i, t ) ;
}

In my test the output was:

2000000037 : 20000.000005
2000000001 : 20000.000000

The first loop did 36 more iterations due to the accumulated floating point error. That may be negligible or even irrelevant in some cases, but it is a common source of confusion, error and non-deterministic behaviour that you may need to be cautious of.

That is not the most serious issue however. If the target value is very large and the increment very small, the first loop may never terminate because the increment must first be normalised to the same precision as the value of t and the nature of floating point representation is such that the increment may become zero. double is good for approximately 15 significant figures do if say:

              __15 digits__
             /              \
target    == 1000000000.00000
increment ==          0.00000100000000000000
                             \__15 digits__/
// After normalisation:
increment == 0000000000.00000
             \__15 digits__/

increment is smaller than the precision of target, so when increment is transformed to the same precision, being smaller than that precision, it becomes zero, and no increment occurs. The problem becomes more acute if you use float which is good for only 6 significant decimal digits.

Specifically with respec to your code:

    #define INCREMENT 0.00001
    ...

    double t = INCREMENT; 
    ...

 // 10.2 Calculate the simulated stopping distance
    int i = 0 ;
    while( v >= 0)
    { 
     a = - f - (C_d)*(v*v); 

     // Calculate the new position 
     x_new = x + (v*t);  

     // Calculate the new velocity
     v_new = v + (a*t);

     x = x_new;
     v = v_new;

     // Increment t
     i++ ;
     t = i * INCREMENT ;

     // ++t;           // Not this
     // t += INCREMENT // or this

    }
Related