Усечение числа с плавающей запятой без округления - PullRequest
21 голосов
/ 12 ноября 2011

У меня есть число с плавающей запятой, которое я хочу обрезать до 3 мест, но не хочу округлять.

Например, преобразовать 1.0155555555555555 в 1.015 (не 1.016).

Как мне поступить в Ruby?

Ответы [ 7 ]

21 голосов
/ 29 октября 2015

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

1.237.to_d.truncate(2).to_f # will return 1.23
21 голосов
/ 12 ноября 2011

Если у вас есть float, попробуйте это:

(x * 1000).floor / 1000.0

Результат:

1.015

Посмотрите, как работает онлайн: ideone

11 голосов
/ 31 июля 2017

Поскольку ruby ​​2.4 Float#truncate метод принимает в качестве необязательного аргумента количество десятичных цифр:

1.0155555555555555.truncate(3)
# => 1.015
8 голосов
/ 12 ноября 2011

Умножьте на тысячу, пол, разделите на тысячу, убедившись, что делите поплавок.

(x * 1000).floor / 1000.0

Или в Ruby 1.9.2, используя версию раунда, которая не была доступна в более ранних версиях,

(x - 0.0005).round(3)
2 голосов
/ 12 октября 2016

sid отвечает хорошо, но он не соответствует первому требованию и, таким образом, не проходит тест Анвара.при наличии требования мы должны начать raw, чтобы ruby ​​не конвертировал число с готовностью.и запускать raw при получении raw - это использовать простую строку, поэтому

> "59.99999999999999999999".to_d.truncate(2)
=> #BigDecimal:55a38a23cd68,'0.5999E2',18(45)>
> "59.99999999999999999999".to_d.truncate(2).to_s
=> "59.99"
> "59.99999999999999999999".to_d.truncate(2).to_f
=> 59.99

просто делюсь этим сейчас, так как я только что столкнулся с этой проблемой сегодня:

0 голосов
/ 29 декабря 2017

Вы можете сделать это с помощью регулярных выражений, поскольку ruby ​​/ rails имеют предел точности.

- сначала преобразуйте число в строку, а затем выполните следующее -

input = "114.99999999999999999999"

вход [/ \ d +. \ D /]

114.99

0 голосов
/ 23 октября 2017

Это решение основано на блестящем трюке BigDecimal от @SidKrishnan, но может также обрабатывать большие поплавки без сбоев по точности.

# Truncate a floating-point value without rounding up.
#
#   trunc_float(1.999, 2)   # => 1.99
#   trunc_float(1.999, 0)   # => 1.0
#
# @param value [Float]
# @param precision [Integer]
# @return [Float]
def trunc_float(value, precision)
  BigDecimal(value.to_s).truncate(precision).to_f
end

#--------------------------------------- Test

describe ".trunc_float" do
  def call(*args)
    trunc_float(*args)
  end

  it "generally works" do
    [
      [[1, 0], 1.0],
      [[1.999, 4], 1.999],
      [[1.999, 3], 1.999],
      [[1.999, 2], 1.99],
      [[1.999, 1], 1.9],
      [[1.999, 0], 1.0],
      [[111111111.9999999, 3], 111111111.999],
      [[1508675846.650976, 6], 1508675846.650976],
    ].each do |input, expected|
      output = call(*input)
      expect([input, output]).to eq [input, expected]
    end
  end
end
...