如何在哈希中舍入一个值?

时间:2018-06-01 12:36:34

标签: ruby

在举重的情况下,我试图计算杆的每一侧所需的板数,假设要提升的总重量和假设45磅的杆。最小的板是2.5磅,我想要舍入到每侧所需的最接近的2.5磅板数。目前,给定140磅的总重量,结果如下:

{:"45"=>1, :"2.5"=>0.8}

如何才能将最接近的整数(0或1)四舍五入为' 2.5'板?

def plates_for(lb)
lb = (lb - 45) / 2
  plate_values = {'45': 45, '25': 25,'10': 10, '5': 5, '2.5': 2.5}
  pairs = plate_values.map do |plate, weight|
    number_of_plates = lb / weight
    lb = lb % weight
    [plate, number_of_plates]
  end

  plates_needed = pairs.select { |plate, weight| weight > 0 }
  p plates_needed.to_h
end

plates_for(140)

2 个答案:

答案 0 :(得分:1)

原始回答:

plates_needed[:'2.5'] = plates_needed[:'2.5'].round

默认情况下,这将四舍五入到最接近的整数,如果它在中途,则向上。如果您希望使用不同的行为进行舍入到最近的一半,则可以指定可选关键字:

2.5.round(half: :up)      #=> 3 (DEFAULT)
2.5.round(half: :down)    #=> 2
2.5.round(half: :even)    #=> 2
3.5.round(half: :up)      #=> 4 (DEFAULT)
3.5.round(half: :down)    #=> 3
3.5.round(half: :even)    #=> 4

或者,如果你想_always_round down,那么使用Integer#floor;如果您希望始终向上舍入,请使用Integer#ceil

完整解决方案:

def plates_for(lb)
  lb = (lb - 45).to_f / 2
  plate_values = [45, 25, 10, 5, 2.5]
  pairs = plate_values.map do |weight|
    number_of_plates = (lb / weight).round
    lb -= number_of_plates * weight
    [weight, number_of_plates]
  end.to_h

  pairs.select { |weight, number_of_plates| number_of_plates > 0 }
end

p plates_for(140) #=> {45=>1, 5=>1}

我已经更改了代码的几个细微部分。请注意,我的代码中的最终结果是不同!我得到{45=>1, 5=>1},这是正确的。变化是:

  • 在第2行添加了to_f。如果没有这个,如果所需的总重量是偶数,则按0.5向下调整条形每一侧所需的重量。例如,(140 - 45) / 2 == 47,但(140 - 45).to_f / 2 == 47.5
  • plate_values定义为简单的Array,以避免混淆。无需将其初始化为Hash
  • Integer#round添加到计算板数。这可以防止在此处分配非整数值。如上所述,您可以选择在此处使用变体。
  • 由于(lb / weight).round可能lb % weight相同(即如果我们向上舍入!),则在此处使用此值是错误的。始终扣除我们实际添加到栏中的重量。
  • 为简化起见,请立即对此映射的结果调用.to_h
  • 为简化起见,无需在下面指定其他变量。

答案 1 :(得分:0)

这就是我接近它的方式:

def plates_for(lb)
  lb = (lb - 45).fdiv(2)
  plate_values = { '45': 45, '25': 25, '10': 10, '5': 5, '2.5': 2.5 }
  pairs = {}
  plate_values.each do |plate, weight|
    pairs[plate], lb = lb.divmod(weight)
  end
  pairs[:'2.5'] += 1 if lb > 0
  pairs.select { |_, count| count > 0 }
end

plates_for(140) #=> {:"45"=>1, :"2.5"=>1}

值得注意的变化:

  • 我使用fdiv将剩余的 lb 转换为十进制数。
  • 在循环中,我通过divmod计算余数,以确保板数为整数。
  • 在循环之后,如果剩余部分还不为零,我会添加另一个2.5牌。