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\$
3
  • 1
    \$\begingroup\$ You seem to be reinventing the wheel. StandardDeviation() StandardDeviationP() \$\endgroup\$ Commented Feb 16, 2015 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
    Commented Feb 16, 2015 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
    Commented Feb 17, 2015 at 0:44

3 Answers 3

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\$
0
5
\$\begingroup\$
double mean = numberSet.Average();
double mean = numberSet.Sum() / numberSet.Count;

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

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

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

\$\endgroup\$
1
  • \$\begingroup\$ If performance is important, also don't use LINQ. \$\endgroup\$ Commented Feb 16, 2022 at 3:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.