在计算阵列中的平均值时返回无穷大

时间:2017-10-17 22:55:06

标签: ruby average reduce infinity

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

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

1 个答案:

答案 0 :(得分:1)

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

这是一个固定的,更像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。首都具有重要意义,并表示类,模块和常量名称等常量。

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

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?可能是您需要删除垃圾数据的。