Use an improved extension method to calculate standard deviation in C#

[standard deviation]

The example Calculate standard deviation in C# makes an extension method that calculates standard deviation for an IEnumerable of integers.

Unfortunately because that example works with integers, it cannot work with other data types. Rian Meier showed me this method, which uses generics to work with other data types.

The new method applies to the generic type IEnumerable<T>. Ideally it would be nice to restrict the generic type T to numeric types, but C# doesn’t have a syntax for that.

Rian’s solution was to use the following code to test the elements in the IEnumerable to see if they can be converted into doubles.

double testDouble;
bool isNumeric = values.All(
    value => double.TryParse(value.ToString(), out testDouble));
if (!isNumeric)
    return double.NaN;

That works but I prefer to throw an exception instead of returning NaN. That way a programmer cannot accidentally think the returned result is a standard deviation. If there is a problem, it will be immediately obvious so the programmer can fix it.

The following code shows the new extension method.

// Return the standard deviation of an array of Doubles.
//
// If the second argument is True, evaluate as a sample.
// If the second argument is False, evaluate as a population.
public static double StdDev<T>(this IEnumerable<T> values,
    bool as_sample)
{
    // Convert into an enumerable of doubles.
    IEnumerable<double> doubles =
        values.Select(value => Convert.ToDouble(value));

    // Get the mean.
    double mean = doubles.Sum() / doubles.Count();

    // Get the sum of the squares of the differences
    // between the values and the mean.
    var squares_query =
        from double value in doubles
        select (value - mean) * (value - mean);
    double sum_of_squares = squares_query.Sum();

    if (as_sample)
    {
        return Math.Sqrt(sum_of_squares / (doubles.Count() - 1));
    }
    else
    {
        return Math.Sqrt(sum_of_squares / doubles.Count());
    }
}

The code first calls the original IEnumerable list’s Select method to “project” the original items into doubles and saves the result in a new IComparable<double>. If the items in the IEnumerable cannot be converted into doubles, this statement fails and throws an exception.

After this the method works exactly as before. See the previous example for information about calculating the standard deviation.


Download Example   Follow me on Twitter   RSS feed   Donate




About RodStephens

Rod Stephens is a software consultant and author who has written more than 30 books and 250 magazine articles covering C#, Visual Basic, Visual Basic for Applications, Delphi, and Java.
This entry was posted in algorithms, extension methods, mathematics and tagged , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *