Подтвердить что ты не робот

Ruby round float to_int, если целое число

В ruby ​​я хочу преобразовать float в int, если это целое число. Например

a = 1.0
b = 2.5

a.to_int_if_whole # => 1
b.to_int_if_whole # => 2.5

В основном я стараюсь избегать отображения ".0" на любое число, которое не имеет десятичного числа. Я ищу элегантный (или встроенный) способ сделать

def to_int_if_whole(float)
  (float % 1 == 0) ? float.to_i : float
end
4b9b3361

Ответ 1

Это решение, которое закончилось тем, что я хочу:

class Float
  alias_method(:original_to_s, :to_s) unless method_defined?(:original_to_s)

  def is_whole?
    self % 1 == 0
  end

  def to_s
    self.is_whole? ? self.to_i.to_s : self.original_to_s
  end
end

Таким образом, я могу обновить логику is_whole? (я думаю, что tadman является самым сложным), если это необходимо, и гарантирует, что в любом месте Float выдает строку (например, в форме), она появляется так, как я хочу это к (то есть, нет нулей на конце).

Спасибо всем за ваши идеи - они действительно помогли.

Ответ 2

Один простой способ:

class Float
  def prettify
    to_i == self ? to_i : self
  end
end

Это потому, что:

irb> 1.0 == 1
=> true
irb> 1 == 1.0
=> true

Тогда вы могли бы сделать:

irb> 1.0.prettify
=> 1

irb> 1.5.prettify
=> 1.5

Ответ 3

Один лайнер sprintf...

sprintf("%g", 5.0)
=> "5"

sprintf("%g", 5.5)
=> "5.5"

Ответ 4

Я не знаю много о Ruby.

Но это проблема отображения. Я был бы очень удивлен, если библиотеки, которые вы используете, не имеют возможности форматировать число при преобразовании его в строку.

Может быть, не все параметры форматирования, которые делают именно то, что вы хотите, но вы можете настроить метод, который возвращает значение true, если float - это представление с плавающей точкой целого числа и false в противном случае. Внутри процедуры форматирования, которую вы создаете (так что вам нужно сделать это только один раз), просто измените форматирование на основе, если это правда или false.

В этом разделе обсуждается, как управлять количеством цифр, которые появляются после десятичного числа при отображении числа.

Следите за сложностями представлений с плавающей запятой. Математика может сказать, что ответ 3, но вы можете получить 3.000000000000000000001. Я бы предложил использовать дельта, чтобы увидеть, является ли число почти целым числом.

Ответ 5

Хотя я бы согласился с вышеуказанным сообщением, если вы должны это сделать:

(float == float.floor) ? float.to_i : float

Ответ 6

Если вы используете рельсы, вы можете использовать хелпер number_to_rounded с опцией strip_insignificant_zeros, например:

ActiveSupport::NumberHelper.number_to_rounded(42.0, strip_insignificant_zeros: true)

или вот так:

42.0.to_s(:rounded, strip_insignificant_zeros: true)

Ответ 7

Здесь моя ужасно хакстастическая реализация, предусмотренная для образовательных целей:

class Float
  def to_int_if_whole(precision = 2)
    ("%.#{precision}f" % self).split(/\./).last == '0' * precision and self.to_i or self
  end
end

puts 1.0.to_int_if_whole # => 1
puts 2.5.to_int_if_whole # => 2.5
puts 1.9999999999999999999923.to_int_if_whole # => 2

Причиной использования вызова стиля sprintf является то, что он обрабатывает приближения с плавающей запятой гораздо более надежно, чем метод round-float # round стремится к.

Ответ 8

Я тоже мало знаю о Ruby.

Но в С++ я бы сделал это:

bool IsWholeNumber( float f )
{
    const float delta = 0.0001;
    int i = (int) f;
    return (f - (float)i) < delta;
}

И тогда я бы форматировал выходную точность на основе этого.