Skip to content

Instantly share code, notes, and snippets.

@Bodacious
Last active May 13, 2016 16:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Bodacious/182584fe27ff3dc70d0a81e8a8000adc to your computer and use it in GitHub Desktop.
Save Bodacious/182584fe27ff3dc70d0a81e8a8000adc to your computer and use it in GitHub Desktop.
How to find an average value, without having to store every data point

How to find an average value, without having to store every data point

This was a solution to a problem I was trying to solve on my webiste: how can I arrive at an average value over time, when new data is being provided, without having to store every datum.

I wrote this code to prove to myself that I wasn't crazy, and that this was indeed a valid way to calculate the mean.

# Collect 100 random data
values = 100.times.map { rand(100) }
# This is the original average of the values
start_average = values.inject(:+) / 100.0
# Print out to the console to prove you're not crazy
puts "Start average:"
puts start_average
# Add another value to the array to get a new average value. This simulates the case where every data point is stored, and
# the average is calculated the "old fashioned way", with every data available.
puts "New average with extra datum:"
puts (values + [200]).inject(:+) / 101.0
# Can't stop creating objects for everything :neckbeard:
class NewAverageCalculator
attr_accessor :new_value, :data_count, :current_average
# Create a new calculator.
#
# new_value - The new datum added to the set
# current_average - The previously calculated average value of all data
# data_count - The total number of data previously collected
def initialize(new_value, current_average, data_count)
@average = current_average
@index = data_count
agreggate_average(new_value)
end
# The new average value
#
# Returns a Float
def new_average
@new_average
end
private
def agreggate_average(new_value)
@new_average = Rational((@average * @index) + new_value, @index + 1).to_f
@index += 1
return @new_average
end
end
puts "Current average:"
puts NewAverageCalculator.new(200, start_average, 100).new_average
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment