2

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;
    }
dbush
  • 205,898
  • 23
  • 218
  • 273
ImDrum
  • 21
  • 3
  • 2
    Make an attempt. Then if you get stuck, come back with a **specific** question. – dbush Jun 04 '21 at 14:12
  • What is the problem? One thing that you should be aware though is that your numbers would be not precisely these because `double` can't represent them exactly. See [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Eugene Sh. Jun 04 '21 at 14:12
  • 1
    It is hard to assist if we don't know what your problem is. If it that `t += 0.00001 ;` (or `t = t + 0.00001 ;`) has not ocurred to you, or have you discovered that incrementing a binary floating-point value by a decimal causes a "drift" away from the expected value? – Clifford Jun 04 '21 at 14:17
  • 1
    To what @Clifford said - to avoid the accumulating drift, you can have an *integer* counter `i` and have `t=i*0.00001`. Also will have preventing the case when `t` and `t+0.00001` are actually resulting in the same representation (that's it will no longer be incrementing). – Eugene Sh. Jun 04 '21 at 14:18
  • I’ve edit the question and posted my code up there.Kindly have a look thanks! – ImDrum Jun 04 '21 at 14:24
  • How do you think `++t` is supposed to increment t by `0.00001`? – Eugene Sh. Jun 04 '21 at 14:26
  • I was trying to update the x and v with a new x and v with an increment of 0.00001 second until the updated v is a negative value – ImDrum Jun 04 '21 at 14:27
  • Yeah I have no idea how to do the 0.00001 increment so please ignore that – ImDrum Jun 04 '21 at 14:28
  • 1
    Do you all think it might be fair to let the OP respond to comments (as he has done) before voting to close? – Clifford Jun 04 '21 at 14:36
  • @Maxx You would do well to include the data types in your code fragment. The difference in behaviour given the use of `double` or `float` can be significant. – Clifford Jun 04 '21 at 15:31
  • There is no question in your post except “Can anyone please help?” Edit your post to ask a specific question. Is the code you have not working? What does it do wrong? Explain what it is doing (preferably add `printf` statements to show values as it goes) and explain what you want it to do instead. Edit the question to provide a [mre]. – Eric Postpischil Jun 04 '21 at 15:32
  • As others have pointed out, you can't repeatedly add `0.00001` to a `double` without running into rounding errors. But why do you need to ? Perhaps `int us=0;// elapsed time in microseconds ... us+=10;` would solve the problem. – Tim Randall Jun 04 '21 at 15:41

2 Answers2

1

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 ++;
}
Eugene Sh.
  • 17,802
  • 8
  • 40
  • 61
1

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

    }
Clifford
  • 88,407
  • 13
  • 85
  • 165
  • I see! I think I get the idea now thank man! – ImDrum Jun 04 '21 at 15:06
  • Usually, though, when solving an ODE, *v* (and *x*) are updated using the *increment* *dt*, not the total time. – Bob__ Jun 04 '21 at 15:47
  • @Bob__ Indeed, but the OP had not posted code or indicated the application when I originally write the answer. As I said, it may or may not matter depending on the application, bad a novice understanding the gotcha and getting int good habits is important. – Clifford Jun 04 '21 at 16:03