12
\$\begingroup\$

We were discussing Standard Deviations in chat, so I decided to write a standard deviation calculator:

static double PopulationStandardDeviation(List<double> numberSet)
{
    double mean = numberSet.Average();

    return Math.Sqrt(numberSet.Sum(x => Math.Pow(x - mean, 2)) / numberSet.Count);
}

static double SampleStandardDeviation(List<double> numberSet)
{
    double mean = numberSet.Sum() / numberSet.Count;

    return Math.Sqrt(numberSet.Sum(x => Math.Pow(x - mean, 2)) / (numberSet.Count - 1));
}

How could these be improved? Because they are both Standard Devation calculators, should I combine them into one method with a header of static double StandardDeviation(List<double> numberSet, bool isSample)? Are they an optimal solution for the problem?

\$\endgroup\$
  • 1
    \$\begingroup\$ You seem to be reinventing the wheel. StandardDeviation() StandardDeviationP() \$\endgroup\$ – 200_success Feb 16 '15 at 23:09
  • 1
    \$\begingroup\$ @200_success those methods can only be invoked from LINQ to Entities, so something like double? stdDev = EntityFunctions.StandardDeviation(new List<double> { 1, 2, 3 }); will throw an exception. \$\endgroup\$ – mjolka Feb 16 '15 at 23:27
  • 5
    \$\begingroup\$ A method that takes a boolean value as a parameter and behaves differently depending on that value is not one method, but two methods! You should keep them separated. You couldc of coursec implement them using shared functionality, but your public API should offer two methods. :) \$\endgroup\$ – britishtea Feb 17 '15 at 0:44
9
\$\begingroup\$

It's good to have 2 methods. For the reason that @britishtea said in a comment, which is so spot-on I'm just going to quote it verbatim:

A method that takes a boolean value as a parameter and behaves differently depending on that value is not one method, but two methods! You should keep them separated. You couldc of coursec implement them using shared functionality, but your public API should offer two methods. :) – @britishtea

And indeed, this is how the .NET framework does it too (See StandardDeviation() and StandardDeviationP(), thanks @200_success).

At the same time, of course don't repeat yourself. Extract the common logic to a private helper method, and rewrite your public methods in terms of the private one:

private static double StandardDeviation(List<double> numberSet, double divisor)
{
    double mean = numberSet.Average();    
    return Math.Sqrt(numberSet.Sum(x => Math.Pow(x - mean, 2)) / divisor);
}

static double PopulationStandardDeviation(List<double> numberSet)
{
    return StandardDeviation(numberSet, numberSet.Count);
}

static double SampleStandardDeviation(List<double> numberSet)
{
    return StandardDeviation(numberSet, numberSet.Count - 1);
}

Lastly, the parameter name "numberSet" is a misnomer, suggesting a Set, when it's really a List.

\$\endgroup\$
5
\$\begingroup\$
double mean = numberSet.Average();
double mean = numberSet.Sum() / numberSet.Count;

I would stick to using numberSet.Average() in both cases.

\$\endgroup\$
2
\$\begingroup\$

Performance-wise, use (x - mean) * (x - mean) instead of Math.Pow(x - mean, 2).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.