Search code examples
c++numerical-methodsnumerical-analysis

If statement not evaluating TRUE when it should


I have an array of "x" values (a grid for a PDE solver) that when I pass to a function that fills another array based on these x-values, a particular expression involving one x-value does not evaluate properly. The x-values range is -1:1 at an increment of 0.0125, and at x = -0.5, and at x = 0.5, I need to handle these cases differently than the other values. However the block below fails to evaluate to TRUE for the point x = 0.5 (it's ok for x = -0.5). Here's a stripped down snippet of the problem block, with details to follow:

int N = 160;
double delta_x = 0.0125;
const double lims = 0.5 * delta_x;

for(int i = 0; i <= N; i++)
{                                
  if((x[i] < -0.5) || (x[i] > 0.5)) sol[i] = 0;
  else if( (abs(x[i] + 0.5) < lims) || (abs(x[i] - 0.5) < lims) )  sol[i] = 0.5;
  else sol[i] = 1;

  cout << setprecision(30) << "lims: " << lims << ", abs(x[i] - 0.5): " << abs(x[i] - 0.5) << endl;
  cout << "sol[" << i << "]: " << sol[i] << endl;                                                                                         
}

Here is the output for x = 0.5:

lims: 0.00625000000000000034694469519536, abs(x[i] - 0.5): 1.11022302462515654042363166809e-16
sol[120]: 0

So, it's looks like the expression in the if-statement should return TRUE when x = 0.5, even though it's not precisely 0.5 of course, since it is within the "lims" of the range. Any thoughts??


Solution

  • Answer to the original question

    The expression in the if statement did evaluate true. If it did not, then you would not have seen the output that you included in the question.

    FWIW, a simpler test would be for

    abs(abs(x[i]) - 0.5) < lims
    

    Answer to the latest version of the question

    if((x[i] < -0.5) || (x[i] > 0.5)) sol[i] = 0;
    else if( (abs(x[i] + 0.5) < lims) || (abs(x[i] - 0.5) < lims) )  sol[i] = 0.5;
    else sol[i] = 1;
    

    You state that x[i] is close to 0.5, but does not set sol[i] to 0.5 and in fact sets it to 0. In which case the only sane conclusion is that x[i] > 0.5 and the first condition is is met:

    if((x[i] < -0.5) || (x[i] > 0.5)) sol[i] = 0;
    

    So you need to change the order of your tests:

    if( (abs(x[i] + 0.5) < lims) || (abs(x[i] - 0.5) < lims) )  sol[i] = 0.5;
    else if((x[i] < -0.5) || (x[i] > 0.5)) sol[i] = 0;
    else sol[i] = 1;
    

    And I would write it like this:

    if (abs(abs(x[i]) - 0.5) < lims)
        sol[i] = 0.5;
    else if ((x[i] < -0.5) || (x[i] > 0.5)) 
        sol[i] = 0;
    else 
        sol[i] = 1;
    

    Please in future be sure to include the right code in the question that you ask.