Something wrong with my standard deviation function



Oops, try again. grades_std_deviation(7.6875) returned 18.2776094147 instead of the expected: 2.7726341266


grades = [100, 100, 90, 40, 80, 100, 85, 70, 90, 65, 90, 85, 50.5]

def print_grades(grades):
    for grade in grades:
        print grade

def grades_sum(grades):
    total = 0
    for grade in grades: 
        total += grade
    return total
def grades_average(grades):
    sum_of_grades = grades_sum(grades)
    average = sum_of_grades / float(len(grades))
    return average

def grades_variance(scores):
    average = grades_average(scores)
    variance = 0 
    for score in scores:
        variance += (average - score)**2
    variance = variance / float(len(scores))
    return variance

print grades_variance(grades)

def grades_std_deviation(variance):
    variance = grades_variance(grades)
    st_dev = variance ** 0.5
    return st_dev

variance = grades_variance(grades)

print grades_std_deviation(variance)


Remove this line from inside the function. Since you are passing variance into the function, this call is only messing up that value.


When the program calls grades_sum() the ball gets rolling. It's the main data getting added up and the author has built in a free un-gotcha. He included a float as the last value of the list. Because of this, we don't have to concern ourselves with floats anywhere in our code. There are nothing but floats in our variables.

This brings us to the usage in the OP code. In both instances it is an integer (more specifically, a counting number) that is being converted to a float. This is not helpful, at all. Who counts, `one point zero, two point zero, ...? We should never make a counting number a float. It follows that if the denominator is an integer, as a counting number, then the value to set as a float is the numerator.

float(5 + 4) / 2    # 4.5
(5 + 4) / 2         # 4
(5 + 4) / 2.0       # 4.5

Python interprets the last one implicitly, yet advises against it. We're mutating an integer.

In both cases, the code,

 / float(len(grades))
 / float(len(scores))

may be written,

 / len(grades)
 / len(scores)


The issue with float mentioned by @mtf makes a lot of difference when you are doing numerical calculations in python. This is mostly constrained to Python 2.x and is fixed in Python 3.x


We’re stuck in 2.x land in these old tracks. It’s still fun, though, eh? I pray they keep the old l a b s, even though Ruby is iffy. We need a sandbox for old code. Even though I know the limitations, I still love the l a b s…


I am faced with this issue as my work revolves around developing statistical models in python. Unit tests usually fail for something very simple like this...