Округление поплавка в рубине


150

У меня проблемы с округлением. У меня есть число с плавающей точкой, которое я хочу округлить до сотых долей. Тем не менее, я могу использовать только то, .roundчто в основном превращает его в int, то 2.34.round # => 2. есть есть простой способ сделать что-то вроде2.3465 # => 2.35

Ответы:


181

При отображении вы можете использовать (например)

>> '%.2f' % 2.3465
=> "2.35"

Если вы хотите хранить его округленным, вы можете использовать

>> (2.3465*100).round / 100.0
=> 2.35

2
Спасибо. Я не знал, что спринтф позаботится о округлении для меня. sprintf '%.2f', 2.3465тоже работает.
Ноа Суссман

66
value.round (2) лучше, чем это решение
Kit Ho

12
Имейте в виду, что 2.3000.round(2) => 2.3и sprintf '%.2f', 2.300 => 2.30. На мой взгляд, это недостаток в round (), или у него должна быть возможность сохранить конечные нули.
Экскалибур

14
@Excalibur 2.3000.round(2)- это число, а не строка. Число не 2.3может отличаться от указанного 2.30, поэтому нет возможности сохранить конечные нули. Вы можете создать свой собственный класс numbers_with_significance, но тогда у нас уже есть строки.
Roobie Nuby

6
Обратите внимание , что , хотя это делает работу для двух знаков после запятой, есть ошибка в '%.3f' % 1.2345(3 знака после запятой, а не 2), однако !! То же самое и для sprintf. Осторожно. Это вернется => 1.234 не так, => 1.235 как многие ожидали бы (ау, после 2-го знака после спринта округляется на 5 вниз и только на 6 вверх). Вот почему вышеупомянутый комментарий Кит Хо имеет более 25 голосов. Безопаснее в использовании, '%.3f' % 1.2345.round(3)поэтому .roundсначала нужно правильно округлить число , а затем отформатировать его (с нулями в конце, если это необходимо).
ликетический

392

Передать аргумент в раунд, содержащий число десятичных знаков, чтобы округлить до

>> 2.3465.round
=> 2
>> 2.3465.round(2)
=> 2.35
>> 2.3465.round(3)
=> 2.347

8
Это казалось бы более разумным, чем умножение, округление и деление. +1
Марк Эмблинг

3
Хм, этот метод, кажется, не в ruby ​​1.8.7. Может в 1.9?
Брайан Армстронг

2
@Брайан. Это определенно в 1,9 и также в рельсах (с которым этот вопрос был помечен)
Стив Вит

3
Метод округления в Ruby 1.8.7 не имеет этой способности, добавление параметра округления до десятичного знака - это способность 1,9
bobmagoo

1
Обратите внимание, что вы не получите конечные нули с этим, поэтому 1.1.round(2)=> 1.1нет1.10
NotAnAmbiTurner

9

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

//to_f is for float

salary= 2921.9121
puts salary.to_f.round(2) // to 2 decimal place                   

puts salary.to_f.round() // to 3 decimal place          

7

Вы можете добавить метод в Float Class, я узнал об этом из stackoverflow:

class Float
    def precision(p)
        # Make sure the precision level is actually an integer and > 0
        raise ArgumentError, "#{p} is an invalid precision level. Valid ranges are integers > 0." unless p.class == Fixnum or p < 0
        # Special case for 0 precision so it returns a Fixnum and thus doesn't have a trailing .0
        return self.round if p == 0
        # Standard case  
        return (self * 10**p).round.to_f / 10**p
    end
end

3

Вы также можете предоставить отрицательное число в качестве аргумента roundметода для округления до ближайшего кратного 10, 100 и так далее.

# Round to the nearest multiple of 10. 
12.3453.round(-1)       # Output: 10

# Round to the nearest multiple of 100. 
124.3453.round(-2)      # Output: 100



1

Если вам просто нужно отобразить его, я бы использовал помощник number_with_precision . Если вам это нужно где-то еще, я бы использовал, как указал Стив Уит, roundметод


1
Обратите внимание, что number_with_precisionэто метод Rails-only.
Смар

0

Для ruby ​​1.8.7 вы можете добавить следующее в ваш код:

class Float
    alias oldround:round
    def round(precision = nil)
        if precision.nil?
            return self
        else
            return ((self * 10**precision).oldround.to_f) / (10**precision)
        end 
    end 
end
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.