Исходный ответ:
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}
, что правильно.Изменения:
- Добавлено
to_f
в строке 2. Без этого вы округляете необходимый вес на каждой стороне бара на 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
в результате этого сопоставления для упрощения. - Нет необходимости назначать другую переменную ниже, для упрощения.