class Mean
Allows calculation of arithmetic, geometric and harmonic means. Class methods allow the passing in of a data set. Alternatively an object can be created and elements can be added with push
Public Class Methods
Calculate the arithmetic mean @param [Array<Numeric>] data the data values @return [Numeric, nil] the arithmetic mean or nil if there is no data
# File lib/means.rb, line 13 def Mean.arithmetic(data) data.sum / data.size unless data.empty? end
Calculate the geometric mean @param (see Mean.arithmetic
) @return [Numeric, nil] the geometric mean or nil if there is no data or any elements are zero or negative
# File lib/means.rb, line 20 def Mean.geometric(data) data.reduce(:*) ** (1 / data.size) unless data.empty? or includes_zero_or_negative? data end
Calculate the harmonic mean @param (see Mean.arithmetic
) @return [Numeric, nil] the harmonic mean or nil if there is no data or any elements are zero or negative
# File lib/means.rb, line 27 def Mean.harmonic(data) data.size / data.reduce(0) {|sum, element| sum += (1 / element)} unless data.empty? or includes_zero_or_negative? data end
Remember the initial state.
If you are passing in an initial state:
- arithmetic mean
-
needs `:sum` and `:count`
- geometric mean
-
needs `:product` and `:count`
- harmonic mean
-
needs `:sum_of_reciprocals` and `:count`
@param [Hash{Symbol => Numeric}] @raise if `:count` is negative @raise if `:sum_of_reciprocals` is negative @raise if `:product` is negative
# File lib/means.rb, line 41 def initialize(params={}) check_params params assign_defaults params end
Private Class Methods
# File lib/means.rb, line 104 def self.includes_zero_or_negative? data data.any? {|element| zero_or_negative? element } end
# File lib/means.rb, line 108 def self.zero_or_negative? element element <= 0 end
Public Instance Methods
Calculate the arithmetic mean @return [Numeric, nil] the arithmetic mean or nil if there is no data
# File lib/means.rb, line 62 def arithmetic_mean @sum / @count unless @count.zero? end
Calculate the geometric mean @return [Numeric, nil] the geometric mean or nil if there is no data or any elements are zero or negative
# File lib/means.rb, line 68 def geometric_mean @product ** (1 / @count) unless @count.zero? or @includes_zero_or_negative end
Calculate the harmonic mean @return [Numeric, nil] the harmonic mean or nil if there is no data or any elements are zero or negative
# File lib/means.rb, line 74 def harmonic_mean @count / @sum_of_reciprocals unless @count.zero? or @includes_zero_or_negative end
Add element to the data set @param [Numeric] element the element to add
# File lib/means.rb, line 48 def push(element) @includes_zero_or_negative = true if Mean.zero_or_negative? element unless @includes_zero_or_negative @sum_of_reciprocals += (1 / element) @product *= element end @sum += element @count += 1 end
Private Instance Methods
# File lib/means.rb, line 87 def assign_defaults params defaults = { sum: 0, sum_of_reciprocals: 0, product: 1, count: 0 } options = params.reverse_merge defaults @sum = options[:sum] @sum_of_reciprocals = options[:sum_of_reciprocals] @product = options[:product] @count = options[:count] @includes_zero_or_negative = false end
# File lib/means.rb, line 80 def check_params params params.assert_valid_keys :count, :sum_of_reciprocals, :product, :sum raise_error_for_negative params, :count raise_error_for_negative params, :sum_of_reciprocals raise_error_for_negative params, :product end
# File lib/means.rb, line 112 def raise_error_for_negative params, key raise %{cannot have negative "#{key.to_s}" of "#{params[key]}"} if params.has_key? key and params[key] < 0 end