Jim Slatten
Jim Slatten

Reputation: 41

Finding average and standard deviation from numbers read from a file

Evening all, I have a problem assignment that asks to write a program that reads in a bunch of numbers from a file and outputs the letter grades, average, and standard deviation. The letter grades and average I have taken care of, but I'm having trouble with the standard deviation. The issue is that my program reads in all the values and calculates the average after it has done so. Since the formula for standard deviation requires using the particular data point AND the average, well, I'm just not sure how to go about it. One idea I had was to try making the program open the file twice, so that on the second run (by which point it has the average calculated) it can calculate the standard deviation. However, the compiler does not like this at all. Any advice?

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;

int main(){
ifstream file("grades.txt");
double number,sum=0,noNumbers=0,average=0;
int noAs=0, noBs=0, noCs=0, noDs=0, noFs=0, noAms=0, noBms=0, noCms=0, noDms=0, noAps=0, noBps=0, noCps=0, noDps=0, quant=0, quanttot=0;

while(file >> number){
    if(number >= 97 && number <=100 ){
    noAps++;
    }
    if(number >= 93 && number < 97){
    noAs++;
    }
    if(number >= 90 && number < 93){
    noAms++;
    }
if(number >= 87 && number <90 ){
    noBps++;
    }
    if(number >= 83 && number < 87){
    noBs++;
    }
    if(number >= 80 && number < 83){
    noBms++;
    }
    if(number >= 77 && number < 80 ){
    noCps++;
    }
    if(number >= 73 && number < 77){
    noCs++;
    }
    if(number >= 70 && number < 73){
    noCms++;
    }
    if(number >= 67 && number < 70 ){
    noDps++;
    }
    if(number >= 63 && number < 67){
    noDs++;
    }
    if(number >= 60 && number < 63){
    noDms++;
    }
    if(number < 60){
    noFs++;
    }
    noNumbers++;
    sum = sum += number;
}
average = sum / noNumbers;
while(file >> number){
    quant = (number - average)*(number-average);
    quanttot = quanttot + quant;
}
double sigma;
sigma = sqrt(quanttot/noNumbers);
cout << "Average is: " << average << endl;
cout << "Standard deviation is: " << sigma << endl;
ofstream newfile("grades2.txt");
newfile <<  "A+'s: " << noAps << endl 
    << "A's: " << noAs << endl 
    <<"A-'s: " << noAms << endl 
    <<"B+'s: " << noBps << endl 
    << "B's: " << noBs << endl 
    << "B-'s: " << noBms << endl 
    <<"C+'s: " << noCps << endl 
    <<"C's: " << noCs << endl 
    <<"C-'s: " << noCms << endl 
    <<"D+'s: " << noDps << endl 
    <<"D's: " << noDs << endl 
    << "D-'s: " << noDms << endl 
    << "F's: " << noFs << endl;
newfile.close();
cout << "Press any key to continue...THEN PRESS ENTER!\n:";
int f;
cin >> f;
return 0;

}


Ah, saving the numbers into an array to manipulate later was a good idea indeed. So I changed my code to this:

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;

int main(){
ifstream file("grades.txt");
double sum=0,noNumbers=0,average=0;
int noAs=0, noBs=0, noCs=0, noDs=0, noFs=0, noAms=0, noBms=0, noCms=0, noDms=0, noAps=0, noBps=0, noCps=0, noDps=0, quant=0, quanttot=0;
int i = 1;
double number[500];
while(file >> number[i]){
while(number[i]<=100){

    if(number[i] >= 97 && number[i] <=100){
    noAps++;
    }
    if(number[i] >= 93 && number[i] < 97){
    noAs++;
    }
    if(number[i] >= 90 && number[i] < 93){
    noAms++;
    }
    if(number[i] >= 87 && number[i] < 90){
    noBps++;
    }
    if(number[i] >= 83 && number[i] < 87){
    noBs++;
    }
    if(number[i] >= 80 && number[i] < 83){
    noBms++;
    }
    if(number[i] >= 77 && number[i] < 80){
    noCps++;
    }
    if(number[i] >= 73 && number[i] < 77){
    noCs++;
    }
    if(number[i] >= 70 && number[i] < 73){
    noCms++;
    }
    if(number[i] >= 67 && number[i] < 70){
    noDps++;
    }
    if(number[i] >= 63 && number[i] < 67){
    noDs++;
    }
    if(number[i] >= 60 && number[i] < 63){
    noDms++;
    }
    if(number[i] < 60){
    noFs++;
    }
    noNumbers++;
    i++;
}
}
for(int i=0; i = noNumbers; i++){
    sum = sum + number[i];
}
average = sum/noNumbers;

for(int i=0; i=noNumbers;i++){
    quant = (number[i] - average)*(number[i] - average);
    quanttot = quanttot + quant;
}

double sigma;
sigma = sqrt(quanttot/noNumbers);
cout << "Average is: " << average << endl;
cout << "Standard deviation is: " << sigma << endl;
ofstream newfile("grades2.txt");
newfile <<  "A+'s: " << noAps << endl 
    << "A's: " << noAs << endl 
    <<"A-'s: " << noAms << endl 
    <<"B+'s: " << noBps << endl 
    << "B's: " << noBs << endl 
    << "B-'s: " << noBms << endl 
    <<"C+'s: " << noCps << endl 
    <<"C's: " << noCs << endl 
    <<"C-'s: " << noCms << endl 
    <<"D+'s: " << noDps << endl 
    <<"D's: " << noDs << endl 
    << "D-'s: " << noDms << endl
    << "F's: " << noFs << endl
    << "Average: " << average << endl
    << "Standard Deviation: " << sigma << endl;
newfile.close();
cout << "Press any key to continue...THEN PRESS ENTER!\n:";
int f;
cin >> f;
return 0;

}

However, now I get a crazy error that forces a break and takes me to some mumbojumbo code within the compiler. Does anyone see any errors that could cause this? To be specific, the error it gives me is in a popup window and says: "Unhandled exception at 0x5A221D7F (msvcp110d.dll) in ConsoleApplication79.exe: 0xC0000005: Access violation reading location 0x4050C000." Also, there are somewhere between 300 and 450 numbers in the text file so the array shouldn't be running out of slots.

Upvotes: 1

Views: 2444

Answers (4)

Alex Reynolds
Alex Reynolds

Reputation: 96966

If you are using C++, consider putting your numbers into a vector.

Once you have a vector, it is pretty easy to write functions that iterate over elements in the vector. Your functions could calculate all kinds of statistics: mean (average), standard deviation, median, etc. Or you can use libraries like Boost to do it for you.

There's really no need to read through the file twice, unless you are dealing with millions of numbers or your machine is somehow constrained for memory, which doesn't appear to be the case here. Store the numbers you're working with into a standard C++ container (a vector) and learn how to work with the contents of that container to get the answers you want.

Upvotes: 3

Charles Pehlivanian
Charles Pehlivanian

Reputation: 2133

There is no need to store anything in a vector or otherwise. All of these statistics can be calculated in one pass, by updating as each new float comes in. You are actually passing through the data 3 times above. Get rid of the vector, and try to do all calculations as the data is being read.

Upvotes: 0

Charles Pehlivanian
Charles Pehlivanian

Reputation: 2133

There is a way to calculate std. deviation in one pass; it's better if you figure it out.

Upvotes: 0

mathematician1975
mathematician1975

Reputation: 21351

I would advise that you read the file into an array or vector (unless the file is too large). Also to avoid potential rounding errors, make your running total variable (double noNumbers) an integer type rather than a floating point type (see this Is using increment (operator++) on floats bad style?)

If the file is small enough if you read into an array you can perform whatever numerical calculations you want without inefficient re-reading of the file content

Upvotes: 0

Related Questions