Rilcon42
Rilcon42

Reputation: 9765

How to add rounding to arrays

I spent some time trying to find a way to do basic operations on each element in an array such as sum, round, etc.

I didn't see a built-in way to do this, so I tried to create my own after finding "Generic 'sum' And 'mean' Methods For Ruby Arrays".

Can someone explain why my round method doesn't work?

class Array
  def sum
    inject(nil) { |sum, x| sum ? sum + x : x }
  end

  def mean
    sum / size
  end

  def round(p)
    inject(nil) { |x| (x * 10 ^ (p-1)).floor / 10 ^ (p - 1) }
  end   
end

puts [1.1234, 1.45656, 1.546567, 1.4577887].mean
puts [1.1234, 1.45656, 1.546567, 1.4577887].round(6)

Upvotes: 0

Views: 571

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110675

You want the following.

class Array
  def sum
    inject(:+)
  end

  def mean
    sum / size.to_f
  end

  def round(p)
    map { |n| n.round(p) }
  end 
end

puts [1.1234, 1.45656, 1.546567, 1.4577887].mean
1.3960789249999999

puts [1.1234, 1.45656, 1.546567, 1.4577887].round(6)
1.1234
1.45656
1.546567
1.457789

Note that sum.to_f (or size.to_f) is needed when the array contains only integers. If arr.sum = 3 and arr.size = 2, sum / size #=> 1 whereas sum / size.to_f #=> 1.5.

Upvotes: 2

ndnenkov
ndnenkov

Reputation: 36101

To answer the why part of your question, there are three issues with your implementation:

  1. Conceptual: inject is used to get a bunch of things and combine them into one thing. Here you have things and want to juxtapose the same number of other things. The method to do that is map:

    [1, 2, 3].inject(:+) # => 6
    [-1, 2, -3].map(&:abs) # => [1, 2, 3]
    
  2. Syntactical: ^ is a bitwise XOR, not power to. To do that, the operator is **.

  3. Basic math: lets make a sanity check by trying to round the number 1.77 one decimal point:

    (17.7).floor / 10 = 1.7

Upvotes: 1

Related Questions