Home > Back-end >  Why is this loop seeming to change the value of a variable?
Why is this loop seeming to change the value of a variable?

Time:10-04

The following code is meant to calculate 7 terms: tcapneg, tcappos, tneg1, tneg2, tpos1, tpos2, tzcap (only the calculation of tpos1 and tpos2 is shown here), and determine the entry that satisfies the condition of being the smallest positive non-zero entry.

int hitb;
double PCLx = 2.936728;
double PCLz = -0.016691;
double PDCx = 0.102796;
double PDCz = 0.994702;
double q = 0.002344;
double s = 0.0266;
double v = 0.0744;
double a = -q * PDCx * PDCx;
double b = s * PDCx - 2 * q*PCLx*PDCx - PDCz;
double c = -1.0*(PCLz   q * pow(PCLx, 2) - s * PCLx   v);
double d = b * b - 4 * a*c;

if (d >= 0.0f) // only take solution if t real
{
    tpos1 = (-b   sqrt(d)) / (2 * a);
    tpos2 = (-b - sqrt(d)) / (2 * a);
}

printf("\n %f %f %f %f %f %f %f", tcapneg, tcappos, tneg1, tneg2, tpos1, tpos2, tzcap);

yielding the result:

 0.000000 0.000000 -40326.381162 -0.156221 -40105.748386 0.000194 0.016780

It is seen that the expected result should be smallest = tpos2 = 0.000194.

double smallest = -1.0;
double tlist[7] = { tcapneg, tcappos, tneg1, tneg2, tpos1, tpos2, tzcap };
const int size = sizeof(tlist) / sizeof(int);
for (int i = 0; i < size; i  )
{
    if (tlist[i] > EPSILON && (smallest == -1.0 || tlist[i] < smallest))
    {
        smallest = tlist[i];
    }
}
printf("\n %f", smallest);

The output for smallest = 0.000192, thus smallest != tpos2 != 0.00194. Why is there this small change in value for the selected smallest entry?

The result of smallest will be fed to the following code:

            if (smallest == tneg1 || smallest == tneg2)
            {
                hitb = 1;
            }
            else if (smallest == tpos1 || smallest == tpos2)
            {
                hitb = 2;
            }
            else if (smallest == tcappos)
            {
                hitb = 3;
            }
            else if (smallest == tcapneg)
            {
                hitb = 4;
            }
            else if (smallest == tzcap)
            {
                hitb = 5;
            }

In this case, we should satisfy the condition to write hitb = 2, however this is failing due to the inequality above.

CodePudding user response:

Probably you never iterate over the last elements of the array: you calculate the size as sizeof(double*) / sizeof(int) which is not true. Just use std::vector type for an array and iterate over it using iterator types:

std::vector<double>tlist = ...
for(auto i = tlist.begin(); i != tlist.end(); i  )
{
    double v = (*i);
    /* ... */
}

Also you should thoroughly check the logic of your condition: is EPSILON positive?

CodePudding user response:

Your array double tlist[7] is in double with 7 elements. sizeof(double) is 8, so sizeof(tlist) is 8*7 = 56. While sizeof(int) is 4, so your size = sizeof(tlist) / sizeof(int) is 56/4 = 14. Your loop goes beyond number of elements in the array. It counts 7 more double values after the array in memory, because the array name is used as a pointer.

Here is my code to verify the above nanalysis

#include <iostream>
using namespace std;
int main()
{
    double da[7] = {0.0, 0.0, -40326.381162, -0.156221, -40105.748386, 0.000194, 0.016780};
    const int sda = sizeof(da);
    const int sin = sizeof(int);
    const int siz = sda/sin;
    cout << "sda:" << sda << " sin:" << sin << " siz:" << siz << endl;

    for( int i=0; i<siz; i   ) {
        cout << "da[" << i << "] = " << da[i] << endl;
    }

    return 0;
}

Here is the output

sda:56 sin:4 siz:14
da[0] = 0
da[1] = 0
da[2] = -40326.4
da[3] = -0.156221
da[4] = -40105.7
da[5] = 0.000194
da[6] = 0.01678
da[7] = 2.07324e-317
da[8] = 8.48798e-314
da[9] = 1.9098e-313
da[10] = 0
da[11] = 1.31616e-312
da[12] = 0
da[13] = 6.95332e-310

The correct code is

size = sizeof(tlist) / sizeof(double);

Use the following option for GCC to report runtime error in this case

g   -fsanitize=bounds -o main.e main.cpp
  • Related