Calculating Standard Deviation & Variance

hi programmers :)
I have these numbers in a file : Random.txt
1.8575
2.99204
1.06594
0.592149
3.3509
1.46936
0.671915
2.23096
-2.0554
-0.5209

I want to calculating Standard Deviation & Variance but i have a problem with it ! Standard Deviation & Variance is 0
can you help me pls?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  #include <fstream>
#include <iostream>
#include <math.h>

int main() {
    std::ifstream infile ("Random.txt");
    double num;
    double total = 0.000f;
    double avr = 0.000f;
    double var = 0.000f;
    double sd = 0.000f;
    unsigned int count = 0;

    // calculate average (and count)
    while(infile >> num) {
        total += num;
        ++count;
        avr = total/count;
    }
    // calculate variance
	while(infile >> num)
	{
 	var += (num - avr)*(num - avr);
	}
        var /= count;

     // calculate Standard Deviation
        sd = sqrt(var);

    infile.close();

    if (!count) {
        std::cerr << "There Is No number!" << std::endl;
        return 1;
    }

    std::cout << "Average: " << avr << std::endl;
    std::cout << "Variance: " << var << std::endl;
    std::cout << "Standard Deviation: " << sd << std::endl;

    std::cin.sync();
    std::cin.get();

    return 0;
}
Last edited on
Line 17: You're doing redundant calculations. There's no point in calculating the average until you know the number of items.

But your first actual issue is how you are extracting data from the file. Line 14: You loop until you can't extract more data. This by itself is fine. But then, line 20: You keep trying to extract data. Your line 20 while loop will never be entered.
If you want to re-open your file from the beginning, one way would be:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int main()
{
    // ...

    // calculate average (and count)
    {
        std::ifstream infile ("Random.txt");
        while(infile >> num) {
            total += num;
            ++count;
        }
        avr = total/count;
    }

    // calculate variance
    {
        std::ifstream infile ("Random.txt");
        while(infile >> num)
	{
 	    var += (num - avr)*(num - avr);
	}
        var /= count;
    }

    // ...
}

(The destructor of an fstream automatically closes the file for you, avoiding explicit open/close calls.)

PS: Your indentation goes a little haywire from line 20 to 26. Try to be more consistent with it; it makes your code easier to read.
Last edited on
Thank you for your explanation. But I'm really in a hurry to do it and my brain is paralyzed!
Can you help correct it?
Although the average works well, the rest of them are right in my opinion, but they are not
I told you what was wrong. I'm not going to just write a complete, working program for you. Maybe somebody else will. What you should do is iterate your design based on what I said, and then post the modified version of your code so that it can be critiqued further if you're still having issues.

By the way, prefer the C++ header <cmath> as opposed to <math.h> for C++ code.
Last edited on
You want to teach fishing instead of giving fish to others. I hope somebody else will.
@changiz, I think the quote is
"Give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime". @Ganado was telling you what was wrong and doing you a favour.

Close the file and reopen it if you want to read the numbers again (although there are far better ways than reading stuff twice).
There's no need to read the file twice - just store the numbers. Consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <fstream>
#include <iostream>
#include <cmath>
#include <vector>

int main()
{
	std::ifstream infile("Random.txt");

	if (!infile)
		return (std::cout << "Cannot open file\n"), 1;

	std::vector<double> vd;
	double total {};

	for (double num {}; infile >> num; ) {
		vd.push_back(num);
		total += num;
	}

	if (vd.empty())
		return (std::cerr << "There Is No number!\n"), 2;

	const double avr {total / vd.size()};
	double var {};

	for (const auto num : vd)
		var += (num - avr) * (num - avr);

	var /= vd.size();

	const double sd {sqrt(var)};

	std::cout << "Average: " << avr << '\n';
	std::cout << "Variance: " << var << '\n';
	std::cout << "Standard Deviation: " << sd << '\n';
}



Average: 1.16545
Variance: 2.3619
Standard Deviation: 1.53685


There's no need to store the numbers either; just form the sum of the numbers and the sum of their squares. There's a simple formula for variance that doesn't require subtracting the average from all numbers first.
seeplus you are my angel of salvation! God bless you
the way I heard it was
build a man a fire and he will be warm for one night. Set a man on fire and he will be warm for the rest of his life.
I like that one.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;

int main()
{
   int N = 0;
   double sumx = 0, sumxx = 0;
   ifstream in( "Random.txt" );
   for ( double x; in >> x; N++ )
   {
      sumx  += x;
      sumxx += x * x;
   }

   double mean     = sumx / N;
   double variance = sumxx / N - mean * mean;
   double sigma    = sqrt( variance );
   cout << "Mean: " << mean << '\n';
   cout << "Variance: " << variance << '\n';
   cout << "Standard deviation: " << sigma << '\n';
   cout << "Unbiased estimate of population s.d: " << sqrt( N * variance / ( N - 1 ) ) << '\n';
}
This is a numerically stable single pass algorithm:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <fstream>
#include <cmath>

int main()
{
    if( std::ifstream file{ "random.txt" } )
    {
        std::size_t n = 0 ; // count
        double mean = 0 ; // running mean
        double m2n = 0 ; // see: https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm

        // update n, mean and m2n for a new value which has arrived
        const auto update = [&] ( double value )
        {
            // Wellford's algorithm
            // "This algorithm is much less prone to loss of precision due to catastrophic cancellation,
            // but might not be as efficient because of the division operation inside the loop."
            // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm
            ++n ;
            const auto delta = value - mean ;
            mean += delta / n ;
            m2n +=  delta * ( value - mean ) ;
        };

        double value ;
        while( file >> value ) update(value) ;

        if( n > 1 )
        {
            std::cout << std::fixed
                      << "           mean: " << mean << '\n'
                      << "       variance: " << m2n / n << '\n'
                      << "sample variance: " << m2n / (n-1) << '\n' ;
        }
    }
}
Topic archived. No new replies allowed.