質問

I wrote a program which looks up data in a separate txt file and then gives the average and the standard deviation. It finds my average but I get an error for Standard deviation. Was wondering anyone could help me fix my code. This is it:

data = File.open("avg_temp.txt", "r+")

contents = data.read

contents = contents.split("\r\n")
#split up array
contents.collect! do |x|
    x.split(',') 
end


sum = 0

contents.each do |x|
#make loop to find average
        sum = sum  + x[1].to_f
end
avg = sum / contents.length
puts "The average temperature of Laguardia Airport from 11/97 - 05/11 is:
#{ avg.round(3)}C (Answer is rounded to nearest thousandth place)"
#puts average


variance = 0
contents.each do |x|
        variance = variance + (x-avg)**2
end

variance = variance / contents
variance = Math.sqrt(variance)
puts variance

I get an error where it at line 27: variance = variance + (x-avg)**2

avg_temp.rb:27:in `-': can't convert Float into Array (TypeError)
    from avg_temp.rb:27:in `block in <main>'
    from avg_temp.rb:26:in `each'
    from avg_temp.rb:26:in `<main>'
役に立ちましたか?

解決 2

Use

variance = variance / contents.size # or contents.length

他のヒント

As your question has been answered, perhaps I can suggest a typical way one would use Ruby to calculate a sample mean and standard deviation:

contents = [1,2,3,4,5,6,7,8,9]
n = contents.size             # => 9
contents.map!(&:to_f)         # => [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
mean = contents.reduce(&:+)/n # => 5.0
sum_sqr = contents.map {|x| x * x}.reduce(&:+) # => 285.0
std_dev = Math.sqrt((sum_sqr - n * mean * mean)/(n-1)) # => 2.7386127875258306
  • 'contents' contains the sample values obtained from the file
  • we may as well convert all the sample values to floats first thing, as you did; otherwise we will have to do something like mean = (x1+x2+...)/n.to_f, which is a bit messy, and we might forget to do it everywhere. contents.map(&:to_f) is the same as contents.map {|x| x.to_f}. ('collect' is another name for 'map'.)
  • contents.reduce(&:+) is the same as contents.reduce {|tot, x| tot + x}, so it just adds up the values. ('inject' is another name for 'reduce'.) We divide this by n to get the mean.
  • contents.map {|x| x * x} produces an array [1,4,9,16,...,81].
  • we then chain this to [1,4,9,16,...,81].reduce(&:+), which adds up the squared values.
  • in calculating the sample standard deviation one divides by n-1. (Divide by n to compute the population standard deviation.) If you want to round that off to, say, 2 decimals, stick .round(2) on the end of the last statement (right after the last right paren).
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top