There is a float number num = 22.0098. How can I format it to limit 3 digits after floating point? I tried sprintf('%.3f',num) but return is 22.010, I need 22.009 though
3 Answers
I can think of using bigdecimal. Not sure though if its an overkill:
require 'bigdecimal'
BigDecimal::new("22.0098").truncate(3).to_f
#=> 22.009
2 Comments
N N
Sorry, using gems are not allowed by requirements
shivam
@NodirNasirov its not a third-party gem.
BigDecimal is a Ruby built-in support.Unfortunately, unlike Float#round, Float#floor does not accept an amount of digits. The below code implements the desired behaviour.
def floor_float input, digits = 3
input.divmod(10 ** -digits).first / (10 ** digits).to_f
end
This might be used as monkey patch:
class Float
def floor_ext digits = 3
self.divmod(10 ** -digits).first / (10 ** digits).to_f
end
end
22.0098.floor_ext
#⇒ 22.009
Probably more succinct variant as suggested by @Stefan:
class Float
def floor_ext digits = 3
div(10 ** -digits).fdiv(10 ** digits)
end
end
22.0098.floor_ext
#⇒ 22.009
Or, one might deal with strings explicitly:
i, f = 22.0098.to_s.split('.')
#⇒ [ "22", "0098" ]
[i, f[0..2]].join('.')
#⇒ "22.009"
2 Comments
Stefan
You can express it more succinct:
input.div(10 ** -digits).fdiv(10 ** digits). Also, within Float, you can omit self.aka.nice
Approximately OK, but strictly speaking, there are about 367 IEEE double precision between 0 and 1 that will be incorrectly rounded up to 3 digits. For example, the nearest Float to 0.009 is less than 9/1000 (it is exactly 0.00899999999999999931998839741709161899052560329437255859375), though it will be floor-printed "0.009". Since the shortest decimal representation to this Float is "0.009", this might appear as the correct answer and fit OP requirements, but it's technically not.
If you know how many digits there are in the integer part, you can format it as a string:
sprintf("%.6s", num)
# => "22.009"
In general, you can adjust the 6 depending on the size of num.
1 Comment
N N
I don't know the number of digits in the integer part
sprintf('%.3f', num - 0.0005)