Matt Matt - 6 months ago 9
Ruby Question

Round a float up if positive, down if negative, to a set number of decimal places

I'm dealing with elapsed hours that should always round up to 1 decimal place, but time in the past needs to round down (so 0.33 hours is 0.4, -0.33 hours is -0.4).

I've briefly written the following but it feels inelegant. Is there a more obvious or more railsy way to do this?

def ceil_to_digits(n, digits = 1)
digits = 10.0 ** digits
if n > 0
return (n * digits).ceil / digits
else
return (n * digits).floor / digits
end
end

n = 0.333
ceil_to_digits(n, 1) => 0.4
ceil_to_digits(n, 2) => 0.34

n = -0.333
ceil_to_digits(n, 1) => -0.4
ceil_to_digits(n, 2) => -0.34

Answer

BigDecimal has various different rounding modes. In this case ROUND_UP would solve your problem:

require 'bigdecimal'

def ceil_to_digits(n, digits = 1)
  BigDecimal.new(n, 0).round(digits, :up)
end

n = 0.333
ceil_to_digits(n, 1) #=> 0.4
ceil_to_digits(n, 2) #=> 0.34

n = -0.333
ceil_to_digits(n, 1) #=> -0.4
ceil_to_digits(n, 2) #=> -0.34