Reputation: 12625
I want to convert a BigDecimal object to a currency value to two decimal places. I don't want any rounding. How can I do it?
None of the following approaches worked:
v = BigDecimal("7.1762")
w = BigDecimal("4.2")
v.to_s('2F') # => "7.17 62"
v.to_s('F') # => "7.1762"
v.to_s('%0.2F') # => "0.71762E1"
v.to_s('%0.2f') # => "0.71762E1"
v.truncate(2).to_s('F') # => "7.17" # This one looks like it worked
w.truncate(2).to_s('F') # => "4.2" # But it doesn't pad with the trailing zero(es)
Upvotes: 22
Views: 15585
Reputation: 3669
The comments on the accepted answer contain important information.
It's been rightly pointed out that in older versions of Ruby, using "%.2f" % v
will result in v
being implicitly converted to a floating-point number, causing potential loss of precision/accuracy - e.g. "%.2f" % (10**24) == "999999999999999983222784.00"
You can convert BigDecimal
to String
accurately, even in older Rubies, by using .to_s("F")
. This returns the number in fixed-point format, with a decimal point followed by zero or more decimal digits.
If you add "00"
onto the end of the number (to ensure it has two or more decimal digits), then you can then strip it down using a regex like /.*\..{2}/
(any characters; a decimal point; then two more characters), so it only keeps the first two digits after the decimal point.
require 'bigdecimal'
w = BigDecimal("4.2")
w.truncate(2).to_s("F") # => "4.2"
(w.truncate(2).to_s("F") + "00") # => "4.200"
(w.truncate(2).to_s("F") + "00")[ /.*\..{2}/ ] # => "4.20"
Upvotes: 8
Reputation: 1308
I think this should work, although a little verbose:
money_amount = BigDecimal.new(100)
money_amount.truncate(2).to_s('F').ljust(money_amount.truncate(0).to_s('F').length + 1, '0')
Upvotes: 0
Reputation: 1493
Simply formatting with '%.2f'
should work
v = BigDecimal("7.1233")
"%.2f" % v #=> "7.12"
v = BigDecimal("7.1")
"%.2f" % v #=> "7.10"
Upvotes: 6
Reputation: 369424
How about combining BigDecimal#truncate
and String#%
? :
"%.2f" % BigDecimal("7.1762").truncate(2)
# => "7.17"
"%.2f" % BigDecimal("4.2").truncate(2)
# => "4.20"
Upvotes: 24