0

I've written a program to calculate the chi-squared value using data given. However, I need to write it so that my program can account for not knowing how many lines are in the text file it is reading from. If I define my structure points as point thePoints[1000], (i.e. greater than the number of lines in the file) then the calculations do not work and i end up the 'nan' values. Here's my program:


#include<iostream>
#include<fstream>
#include<cmath>
using namespace std;


//define my own data structure
struct point {
    double x;
    double y;
    double s;
    double w;
    double wx;
    double wy;
    double wxy;
    double wxx;
    double wmxcy;
};


//main program
int main() {

    //array of point
    point thePoints[11];
    int i = 0;

    //open a file to read in
    ifstream myFile ("xys.data.txt");

    //check if it opened successfully
    if (myFile.is_open() ) {

        //file is open
        //read it in
        while (!myFile.eof() ) {

            //whilst we are not at the end of the file
            myFile >> thePoints[i].x >> thePoints[i].y >> thePoints[i].s;
            //increment i
            i++;
        }

        //close the file
        myFile.close();
    }

    // something went wrong
    else {
        cout << "Error opening file!\n";
        exit(1);
    }

    // data is now in an array of point structures

    //set the summation variables to zero - sets an initial value for the rest of the appropriate array to then be added onto
    double Sw = 0;
    double Swxx = 0;
    double Swxy = 0;
    double Swx = 0;
    double Swy = 0;
    double xsq = 0;


    //create an array for w
    for (int j = 0; j <= 10; j++){
        thePoints[j].w = 1/(pow((thePoints[j].s),2));

    //sum over all w i.e. create an array for Sw
        Sw += thePoints[j].w;

    //create an array for wx
        thePoints[j].wx = (thePoints[j].w) * (thePoints[j].x);

    //sum over all wx i.e. create an array for Swx
        Swx += thePoints[j].wx;

    //create an array for wy
        thePoints[j].wy = (thePoints[j].w) * (thePoints[j].y);

    //sum over all wy i.e. create an array for Swy
        Swy += thePoints[j].wy;

    //create an array for wxy
        thePoints[j].wxy = (thePoints[j].w) * (thePoints[j].x) * (thePoints[j].y);

    //sum over all wxy i.e. create an array for Swxy
        Swxy += thePoints[j].wxy;

    //create an array for wxx
        thePoints[j].wxx = (thePoints[j].w) * (thePoints[j].x) * (thePoints[j].x);

    //sum over all wxx i.e. create an array for Swxx
        Swxx += thePoints[j].wxx;
    }

    printf("%6.2f, %6.2f, %6.2f, %6.2f, %6.2f\n", Sw, Swx, Swy, Swxy, Swxx);

    //caluculate a value for D
    double D = ((Sw * Swxx) - (Swx * Swx));

    //calculate a value for m
    double m = ((Sw * Swxy) - (Swx * Swy))/D;

    //calculate a value for dm
    double dm = sqrt(Sw/D);

    //calculate a value for c
    double c = ((Swy * Swxx) - (Swx * Swxy))/D;

    //calculate a value for dc
    double dc = sqrt(Swxx/D);

    //calculate chi-squared value, xsq = Sw(((m * x) + c - y)^2)
    for (int j = 0; j < i; j++){
        thePoints[j].wmxcy = (thePoints[j].w * (pow(((m * thePoints[j].x) + c - thePoints[j].y),2)));

    //sum over all chi-squared
    xsq += thePoints[j].wmxcy;
    }

    //prints all of the results of the data
        printf("The equation of the line for the data is y = %6.2f x + %6.2f.\n", m, c);
        printf("The gradient, m, has an associated error of %6.2f.\n", dm);
        printf("The y intercept, c, has an associated error of %6.2f.\n", dc);
        printf("The data has a chi-squared value of %6.2f.\n", xsq);

    return 0;
}

I have attached the input file.txt file

Any opinions would be much appreciated.

  • 2
    Some places to start reading: http://en.cppreference.com/w/cpp/numeric/math/nan , https://en.m.wikipedia.org/wiki/NaN – Jesper Juhl Nov 23 '17 at 20:49
  • 2
    [why `while (myFile.eof())` is wrong](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – Barmar Nov 23 '17 at 20:50
  • It may be hard to determine the problem without sample input data that reproduces it. – François Andrieux Nov 23 '17 at 20:50
  • You get `inf` and `nan` from things like `1/0` and `0/0`. Check your input data to make sure you're not dividing by zero. – Barmar Nov 23 '17 at 20:51
  • you overflow at some point and may divide by 0 too, so it very depend on data you feed to the program ( the .csv file ) – nullqube Nov 23 '17 at 21:08
  • i have edited my question to include the data that i used – Pooja Gupta Nov 23 '17 at 21:21
  • An image of data makes everybody have to manually transcribe it. Try stepping through the code in a debugger. Look at the value of `i`. It's 12. Why is it 12 even though there are only 11 data points? Pay close attention to the `eof` check. The `eof` bit is set after an attempt to read past the end of the file is made. It's not telling you whether a future read will succeed. – Raymond Chen Nov 23 '17 at 21:43
  • Thank you for your help! I've managed to fix the problem by changing thePoints[1000] to thePoints[11], i.e. tailoring the program exactly to how many lines are included in the data text file. Would anyone know how to adjust this again so that the program accounts for not knowing in advance the number of lines included in the file? – Pooja Gupta Nov 23 '17 at 23:14
  • Please don't keep changing the question. – Raymond Chen Nov 24 '17 at 00:12

1 Answers1

0

If you don't know the number of points at compile time then you should use dynamically allocated memory. You can either read the file in two passes to count the number of points, then allocate the memory all at once with new and populate the points during a second pass, or you can use a data structure to store your points that can grow as needed while you read the file. I would suggest you take a look at std::vector from the STL as a starting place. Here's a brief example using std::vector.

//vector of point
std::vector<point> thePoints;

//open a file to read in
ifstream myFile ("xys.data.txt");

//check if it opened successfully
if (myFile.is_open() ) {

    //file is open
    //read it in
    while (!myFile.eof() ) {
        point aPoint;

        //whilst we are not at the end of the file
        myFile >> aPoint.x >> aPoint.y >> aPoint.s;

        //add a point to the vector of points
        thePoints.push_back(aPoint);
    }

    //close the file
    myFile.close();
}

You can get the number of points with thePoints.size(). Make sure you update all your for loops to remove the hardcoded 10.

Adam
  • 389
  • 1
  • 4
  • 8