In Ruby 2.4+, the Float#float
& Float#ceil
methods take a ndigits
argument:
1.33333333.ceil(2) -> 1.34
1.33333333.floor(3) -> 1.333
However, check out this behavior with those STD lib methods:
# In Ruby 2.4.2:
0.07.ceil(2) -> 0.08
1.1.ceil(2) -> 1.11
Not OK in my book.
For older Ruby versions or if you want to get better results than the STB lib gives, you will need to write your own methods. There are a few different blog posts out there, and I'll explain why they're not consistently correct later, but here are some methods that should work correctly every time:
require 'bigdecimal'
class Float
def ceil2(exp = 0)
BigDecimal(self.to_s).ceil(exp).to_f
end
def floor2(exp = 0)
BigDecimal(self.to_s).floor(exp).to_f
end
end
Now for more on why the following are incorrect:
def ceil_to(x)
(self * 10**x).ceil.to_f / 10**x
end
def floor_to(x)
(self * 10**x).floor.to_f / 10**x
end
# These methods also produce bad results for the examples shown above
0.07.ceil(2) -> 0.08
1.1.ceil(2) -> 1.11
I won't go into the details about what is happening (you can find that
here or here), but floating point arithmetic can be messy and rounding errors do occur.