Handling money in ruby

Neeraj Singh

By Neeraj Singh

on January 14, 2013

In ruby do not use float for calculation since float is not good for precise calculation.

1irb(main):001:0> 200 * (7.0/100)
2=> 14.000000000000002

7 % of 200 should be 14. But float is returning 14.000000000000002 .

In order to ensure that calculation is right make sure that all the actors participating in calculation is of class BigDecimal . Here is how same operation can be performed using BigDecimal .

1irb(main):003:0> result = BigDecimal.new(200) * ( BigDecimal.new(7)/BigDecimal.new(100))
2=> #<BigDecimal:7fa5eefa1720,'0.14E2',9(36)>
3irb(main):004:0> result.to_s
4=> "14.0"

As we can see BigDecimal brings much more accurate result.

Converting money to cents

In order to charge the credit card using Stripe we needed to have the amount to be charged in cents. One way to convert the value in cents would be

1amount  = BigDecimal.new(200) * ( BigDecimal.new(7)/BigDecimal.new(100))
2puts (amount * 100).to_i #=> 1400

Above method works but I like to delegate the functionality of making money out of a complex BigDecimal value to gem like money . In this project we are using activemerchant which depends on money gem . So we get money gem for free. You might have to add money gem to Gemfile if you want to use following technique.

money gem lets you get a money instance out of BigDecimal.

1amount  = BigDecimal.new(200) * ( BigDecimal.new(7)/BigDecimal.new(100))
2amount_in_money = amount.to_money
3puts amount_in_money.cents #=> 1400

Stay in BigDecimal or money mode for calculation

If you are doing any sort of calculation then all participating elements must be either BigDecimal or Money instance. It is best if all the elements are of the same type.

Stay up to date with our blogs. Sign up for our newsletter.

We write about Ruby on Rails, ReactJS, React Native, remote work,open source, engineering & design.