在数组中计算平均值时返回无穷大

Infinity is returned when calculating average in array

为什么以下方法 return 在尝试查找股票的平均交易量时无穷大:

class Statistics

    def self.averageVolume(stocks)
        values = Array.new
        stocks.each do |stock|
            values.push(stock.volume)
        end
        values.reduce(:+).to_f / values.size
    end

end

class Stock
    attr_reader :date, :open, :high, :low, :close, :adjusted_close, :volume
    def initialize(date, open, high, low, close, adjusted_close, volume)
        @date = date
        @open = open
        @high = high
        @low = low
        @close = close
        @adjusted_close = adjusted_close
        @volume = volume
    end

    def close
        @close
    end

    def volume
        @volume
    end
end

CSV.foreach(fileName) do |stock|
    entry = Stock.new(stock[0], stock[1], stock[2], stock[3], stock[4], stock[5], stock[6])
    stocks.push(entry)
end

调用方法的方式如下:

Statistics.averageVolume(stocks)

使用具有 251 行的文件输出到控制台:

stock.rb:32: warning: Float 23624900242507002003... out of range
Infinity

以下行发出警告:values.reduce(:+).to_f / values.size

编写平均函数时,您需要密切注意被零除的可能性。

这是一个固定且更像 Ruby 的实现:

def self.average_volume(stocks)
  # No data in means no data out, can't calculate.
  return if (stocks.empty?)

  # Pick out the `volume` value from each stock, then combine
  # those with + using 0.0 as a default. This forces all of
  # the subsequent values to be floating-point.
  stocks.map(&:volume).reduce(0.0, &:+) / values.size
end

在 Ruby 中,强烈建议将变量和方法名称保持在 x_y 形式,例如此处的 average_volume。大写字母具有重要意义,表示常量,如 class、模块和常量名称。

您可以使用模拟股票测试此方法:

require 'ostruct'

stocks = 10.times.map do |n|
  OpenStruct.new(volume: n)
end

average_volume(stocks)
# => 4.5
average_volume([ ])
# => nil

如果你仍然得到无穷大,那可能是因为 volume 的某个地方有一个破损的值,这把事情搞砸了。您可以尝试过滤掉那些:

stocks.map(&:value).reject(&:nan?)...

nan? 相比,测试可能是您去除垃圾数据所需要的。