我有以下方法来计算平均值:
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
这没什么特别的,但它有一个问题,我希望所有平均方程都有:如果输入全部为零,它可能除以零。
所以,我想到了这样做:
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
......这有效,但对我来说感觉很糟糕。是否有更优雅的“Ruby Way”来避免这种划分为零的问题?
我希望我拥有的是“除非那么”的操作员,比如......
average = numerator / denominator unless denominator == 0 then 0
有什么建议吗?
答案 0 :(得分:60)
您可以使用nonzero?
,如:
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
更多人会更熟悉使用三元运算符(total == 0 ? 1 : total)
,这是另一种可能性。
答案 1 :(得分:7)
通常依靠rescue
捕获异常,然后返回默认值:
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
我也会写:
average = numerator / denominator unless denominator == 0 then 0
作为
average = (denominator == 0) ? 0 : numerator / denominator
答案 2 :(得分:6)
虽然这是一个过时的主题,但我认为我会使用一个简单的衬垫,你可以使用......
@average = variable1 / variable2 rescue 0
答案 3 :(得分:5)
对我而言,最干净的方式是:
numerator / denominator rescue 0
它还可以帮助您避免处理0 / 0
。
正如@Andrew所指出的,这仅对整数有效。有关详细信息,请参阅此答案的评论。
答案 4 :(得分:3)
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
答案 5 :(得分:1)
def compute_average(*values)
# This makes sure arrays get flattened to a single array.
values.flatten!
# Throws away all nil values passed as arguments.
values.reject!(&:nil?)
# Throws away all non-numeric values.
# This includes trashing strings that look like numbers, like "12".
values.keep_if{ |v| v.is_a? Numeric }
total = values.sum.to_f
return Float::NAN if total.zero?
# I'm not sure what this business is
# average = [a, 2*b, 3*c, 4*d, 5*e].sum / total
# but it can be translated to
average = values.each_with_index.map{ |v,i| v*(i+1) }.sum / total
average.round(2)
end
这可以防止所有情况:
compute_average(1,2,3,4,5)
=> 3.67
compute_average(0,0,0,0,0)
=> NaN
compute_average(1,2,nil,4,5)
=> 3.08
compute_average(1,2,"string",4,5)
=> 3.08
compute_average(1)
=> 1.0
compute_average([1,2,3,4,5])
=> 3.67
compute_average
=> NaN
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
def compute_average(a,b,c,d,e)
total = [a,b,c,d,e].sum.to_f
return if total.zero?
average = [a, 2*b, 3*c, 4*d, 5*e].sum / total
average.round(2)
end
此更改仅针对一种情况进行保护:
compute_average(1,2,3,4,5)
# => 3.67
compute_average(0,0,0,0,0)
# => nil
compute_average(1,2,nil,4,5)
# => TypeError: NilClass can't be coerced into Fixnum
compute_average(1,2,"string",4,5)
# => TypeError: String can't be coerced into Fixnum
compute_average(1)
# => ArgumentError: wrong number of arguments calling `compute_average` (1 for 5)
compute_average([1,2,3,4,5])
# => ArgumentError: wrong number of arguments calling `compute_average` (1 for 5)
compute_average
# => ArgumentError: wrong number of arguments calling `compute_average` (0 for 5)
rescue
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 rescue 0
average.round(2)
end
此更改仅针对一个案例进行了保护:
compute_average(1,2,3,4,5)
# => 3.67
compute_average(0,0,0,0,0)
# => NaN
compute_average(1,2,nil,4,5)
# => TypeError: NilClass can't be coerced into Fixnum
compute_average(1,2,"string",4,5)
# => TypeError: String can't be coerced into Fixnum
compute_average(1)
# => ArgumentError: wrong number of arguments calling `compute_average` (1 for 5)
compute_average([1,2,3,4,5])
# => ArgumentError: wrong number of arguments calling `compute_average` (1 for 5)
compute_average
# => ArgumentError: wrong number of arguments calling `compute_average` (0 for 5)
使用内联rescue
会产生另一种后果。考虑一下这个错字:
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].smu / total rescue 0
# ^^^
average.round(2)
end
compute_average(1,2,3,4,5)
# => 0.0
compute_average(0,0,0,0,0)
# => 0.0
rescue
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
这样做更好,因为它不会隐藏错误,但可以防止与上面的rescue
相同的情况。
作为旁注,我熟悉的平均操作是使用总数/计数来计算的,所以这是一个版本。
def compute_average(*values)
# This makes sure arrays get flattened to a single array.
values.flatten!
# Throws away all nil values passed as arguments.
values.reject!(&:nil?)
# Throws away all non-numeric values.
# This includes trashing strings that look like numbers, like "12".
values.keep_if{ |v| v.is_a? Numeric }
total = values.sum.to_f
count = values.count
return Float::NAN if count.zero?
total / count
end
这可以防止所有情况:
compute_average(1,2,3,4,5)
=> 3.0
compute_average(0,0,0,0,0)
=> 0.0
compute_average(1,2,nil,4,5)
=> 3.0
compute_average(1,2,"string",4,5)
=> 3.0
compute_average(1)
=> 1.0
compute_average([1,2,3,4,5])
=> 3.0
compute_average
=> NaN
答案 6 :(得分:0)
我不是一个Ruby-ist,但我会这样做:
average = denominator.nonzero? ? numerator/denominator : 0
可能有更好的答案,但这可能就足够了。
答案 7 :(得分:0)
/
不会返回零分割错误。
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.finite? ? average.round(2) : 0.0
end
更一般地说,在ruby1.9下,
def compute_average *args
average = args.to_enum.with_index.map{|x, w| x * w}.sum / args.sum.to_f
average.finite? ? average.round(2) : 0.0
end