Как округлить целое число дов рубине? - PullRequest
9 голосов
/ 04 августа 2010

Скажите, у меня есть любое из следующих чисел:

230957 или 83487 или 4785

Как в Ruby я могу вернуть их как 300000 или 90000 или 5000 соответственно?

Ответы [ 8 ]

5 голосов
/ 08 октября 2011
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]
5 голосов
/ 04 августа 2010
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
2 голосов
/ 17 июля 2012

В Rails вам также может понравиться помощник "number_to_human", который автоматически выбирает хорошее измерение для округления до.

http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_to_human

1 голос
/ 01 ноября 2013

Math.round принимает отрицательные числа.Если вы ищете только ближайшие 10, вы можете сделать (my_num).round(-1).

Единственный недостаток в том, что здесь нет никакого способа включить ceil, поэтому он не всегда округляется вверх - 4.round(-1) будетвозврат 0.

1 голос
/ 04 августа 2010

На самом деле я не делал никакого кодирования в Ruby, но вы могли бы сделать это с помощью стандартной функции округления, если бы вы поместили ее в число, которое вы хотели сначала.

Пример:

230957 / 100000(the resolution you want) = 2.30957

Round 2.30957 = 2 или Round to Ceiling / Round + 0.5, чтобы заставить его перейти к верхнему значению, а не к нижнему.

2 or 3 * 100000(the resolution you want) = 200000 or 300000 respectively.

Надеюсь, это поможет!

1 голос
/ 04 августа 2010

Это выглядит немного уродливо, но как первый выстрел (раунды вверх каждый раз) ...

>> (("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
0 голосов
/ 19 февраля 2015

Вот моя версия:

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
0 голосов
/ 21 мая 2014

Простое предложение:

def nearest_large_number value
  str = value.to_s.gsub(/^([0-9])/) { "#{$1}." }
  multiplicator = ("1" + "0" * str.split('.')[1].length).to_i
  str.to_f.ceil * multiplicator
end

Чтобы использовать это:

nearest_large_number 230957
=> 300000
...