Standard Deviation Tempate Function

///////////////////////////////////////////////////////////////////////////
// // Pre:
// StandardDeviation //
// // Post:
///////////////////////
template <typename T>
double StandardDeviation( T* array, double elementCount )
{
double mean = Mean( array, elementCount );
double sigma = 0.0;
T* end = array + elementCount;
while ( array < end ) {
//double sigma = ( *array - mean )^2;
sigma += ( ( *array - mean ) * ( *array - mean ) );
array++;
}//endwh
//double standardDeviation = sqrt( sigma / elementCount );
return sqrt( sigma / ( elementCount - 0 ));
}//endfn StandardDeviation

Ignore the commented portions of this function as I was trying to figure the calculations out before I figured out the proper syntax.

Ok what im trying to do is write a Template function that calculates standard deviation. I think i have the calculation part right but let me know if you see any mistakes. The problem im getting is that it says illegal use of floating point value and it opints to the double sigma declaration. I dont know why. In my main I call the function as such.

show( StandardDeviation( iArray, iCount ) );
iArray is an integer array and iCount is the number of integers in that array

Mean( array, elementcount );
This is a call to an averaging function that I wrote that has been tested and is fully functional.
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
#include <cmath>

template <typename T>
double Mean(const T arr[], size_t n)
{
	double mean = 0.0;
	for (size_t idx = 0; idx < n; idx++)
	{
		mean += arr[idx];
	}
	mean /= static_cast<double>(n);
	return mean;
}

template <typename T>
double StDev(const T arr[], size_t n)
{
	double mean = Mean(arr, n);
	double variance = 0.0;
	for (size_t idx = 0; idx < n; idx++)
	{
		double temp = arr[idx] - mean;
		variance += temp*temp;
	}

	// Compute sample variance using Bessel's correction (see http://en.wikipedia.org/wiki/Bessel%27s_correction)
	variance /= static_cast<double>(n) - (n == 1 ? 0.0 : 1.0);	

	// Standard deviation is square root of variance
	return std::sqrt(variance);
}


Note that internally, a floating point type is used, since intermediate results may be nonintegral. The template parameter is only really needed to dereference into the array correctly.
why not to use T mean;? and also (n == 1 ? 0.0 : 1.0) is a bit ugly, you could simply write (n != 1). and of course it is much safer to first do integer subtraction and then typecast.
Last edited on
The mean of a set of integers is not necessarily an integer, hence the floating point type.
right, so do conversion in return statement, why doing it before every addition? And also (almost) the same holds for variance. It is not only inefficient, you can lose accuracy as well.
thanks guys I got it figured out
@Onanymous
What you say about the mean calculation makes sense. The casts in the code I posted weren't necessary as they were written
1
2
3
4
5
6
7
8
9
10
template <typename T>
double Mean(const T arr[], size_t n)
{
	T sum = 0;
	for (size_t idx = 0; idx < n; idx++)
	{
		sum += arr[idx];
	}
	return sum/static_cast<double>(n);
}

What type would you suggest should live in the body of the loop accumulating the variance term? A "T - double" squared is almost certainly nonintegral, unless the mean just happened to be an integer.

you could simply write (n != 1)
I have learned to avoid relying on the assumption that a Boolean true equals the integer one (I believe it is only guaranteed to be nonzero). In at least one (embedded) system I have worked on, false == 0 (no bits set), but true == -1 (all bits set).
I would concede that
variance /= n - (n == 1 ? 0 : 1);
is better then what I previously had. The cast is not necessary since variance is already a floating type, and you raised the issue of possible loss of precision.
You are absolutely right about variance, sorry. By loss of precision I mean the situation when adding small integer to a double does not change it is value. This can be accumulated quite fast, so I stick to using integer types whenever possible.

C++ standard 3000 section 4.5.6 states:

An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true
becoming one.

I agree that not every compiler vendor is following standards, but they should be kicked and spammed about it. That is why for example I try not to use microsoft C/C++ compilers.

Last edited on
Topic archived. No new replies allowed.