I have the following method to compute an average:
def compute_average(a,b,c,d,e)
total = [a,b,c,d,e].sum.to_f
average = [a, 2*b, 3*c, 4*d, 5*e].sum / total
average.round(2)
end
It's nothing special, but it has a problem that I expect all average equations have: it might divide by zero if inputs are all zero.
So, I thought of doing this:
def compute_average(a,b,c,d,e)
total = [a,b,c,d,e].sum.to_f
if total==0
average = 0.00
else
average = [a, 2*b, 3*c, 4*d, 5*e].sum / total
average.round(2)
end
end
... and that works, but it feels kludgy to me. Is there a more elegant, "Ruby Way" to avoid this division by zero problem?
What I'm wishing I had was an "unless then" operator, like...
average = numerator / denominator unless denominator == 0 then 0
Any suggestions?
You can use nonzero?
, as in:
def compute_average(a,b,c,d,e)
total = [a,b,c,d,e].sum.to_f
average = [a, 2*b, 3*c, 4*d, 5*e].sum / (total.nonzero? || 1)
end
More people would be more familiar with using the ternary operator (total == 0 ? 1 : total)
, so that's another possibility.
It's common to rely on rescue
to capture the exception, then to return the default value:
def compute_average(a, b, c, d, e)
total = [a, b, c, d, e].sum.to_f
average = [ a, 2*b, 3*c, 4*d, 5*e ].sum / total
average.round(2)
rescue ZeroDivisionError
0.0
end
Also I'd write:
average = numerator / denominator unless denominator == 0 then 0
as
average = (denominator == 0) ? 0 : numerator / denominator
While this is an outdated thread I thought I would chime in with a simple one liner you can use...
@average = variable1 / variable2 rescue 0
def compute_average(a,b,c,d,e)
total = (a+b+c+d+e).to_f
total.zero? ? 0 : ((a + 2*b + 3*c + 4*d + 5*e) / total).round(2)
end
To me, the cleanest way is:
numerator / denominator rescue 0
It also saves you from handling 0 / 0
.
As @Andrew points out, this is only valid for integers. See the comments to this answer for more info.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With