Как округлить целое число до Ruby?
скажем, у меня есть следующие номера:
230957 или 83487 или 4785
каков способ в Ruby я мог бы вернуть их как 300000 или 90000 или 5000, соответственно?
8 ответов
def round_up(number)
divisor = 10**Math.log10(number).floor
i = number / divisor
remainder = number % divisor
if remainder == 0
i * divisor
else
(i + 1) * divisor
end
end
С вашего примера:
irb(main):022:0> round_up(4785)
=> 5000
irb(main):023:0> round_up(83487)
=> 90000
irb(main):024:0> round_up(230957)
=> 300000
def round_to_significant_digit(i, significant_digits = 1)
exp = Math.log10(i).floor - (significant_digits - 1)
(i / 10.0 ** exp).round * 10 ** exp
end
>> [230957, 83487, 4785].collect{|i|round_to_significant_digit(i)}
=> [200000, 80000, 5000]
и для дополнительного кредита:
>> [230957, 83487, 4785].collect{|i|round_to_significant_digit(i, 2)}
=> [230000, 83000, 4800]
>> [230957, 83487, 4785].collect{|i|round_to_significant_digit(i, 3)}
=> [231000, 83500, 4790]
в Rails вам также может понравиться помощник "number_to_human", который автоматически выбирает хорошее измерение для округления.
http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_to_human
это выглядит немного уродливо ,но как первый выстрел (раунды до каждый раз) ...
>> (("230957".split("").first.to_i + 1).to_s + \
("0" * ("230957".size - 1))).to_i
=> 300000
лучше (раунды правильные):
>> (230957 / 10 ** Math.log10(230957).floor) * \
10 ** Math.log10(230957).floor
=> 200000
математика.раунд принимает отрицательные числа. Если вы ищете только ближайшие 10, вы можете сделать (my_num).round(-1)
.
единственным недостатком является то, что здесь нет возможности включить ceil, поэтому он не всегда округляется -- 4.round(-1)
возвращает 0.
Я на самом деле не делал никакого кодирования в Ruby, но вы могли бы сделать это со стандартной функцией округления, если бы вы подтолкнули его к цифре, которую вы хотели сначала.
пример:
230957 / 100000(the resolution you want) = 2.30957
круглые 2.30957 = 2
, или круглый к потолку / круглому значению + 0.5
чтобы заставить его перейти к верхнему значению, а не к нижнему.
2 or 3 * 100000(the resolution you want) = 200000 or 300000 respectively.
надеюсь, что это помогает!
простое предложение:
def nearest_large_number value
str = value.to_s.gsub(/^([0-9])/) { "#{}." }
multiplicator = ("1" + "0" * str.split('.')[1].length).to_i
str.to_f.ceil * multiplicator
end
использовать:
nearest_large_number 230957
=> 300000
вот мой вариант:
def round(num, nearest = nil, pivot = nil)
negative = num < 0
num = -num if negative
precision = Math.log10(num).to_i rescue 1
nearest ||= precision == 0 ? 10 : 10**precision
pivot ||= nearest
result = (num + pivot) / nearest * nearest
negative ? -result : result
end
этот метод очень испорчен и выглядит так уродливо... НО... он обрабатывает несколько крайних случаев, которые другие не такие, как:
- 0
- значения менее 10
- отрицательные числа
- точка поворота может быть изменена
вот несколько примеров использования:
round(0) # 0
round(1) # 10
round(9) # 10
round(10) # 20
round(-10) # -20
round(100) # 1000
round(1, 1000) # 1000
round(499, 1000, 500) # 0
round(500, 1000, 500) # 1000