Read more

BigDecimal arithmetic in Ruby

Henning Koch
April 29, 2011Software engineer at makandra GmbH

Nowadays multiplying or adding BigDecimal with Float results in BigDecimal. This is the case for at least Ruby >= 2.3.

Ruby comes with a class BigDecimal Show archive.org snapshot which you can use for arbitrary precision arithmetic. You should use BigDecimal instead of Float whenever you care about rounding errors, e.g. whenever you are dealing with money.

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

You should remember these two rules when working with BigDecimal values:

  • When you add or multiply a BigDecimal with another BigDecimal, the result will be a new BigDecimal with sufficient precision to represent the result. No rounding or clipping should occur in that operation.
  • When you add or multiply a BigDecimal with a Float, the result will be a Float. That means you just transitioned back into the land of random rounding errors.

Don't screw up your clean BigDecimal values by thoughtlessly multiplying them with a Float. For instance, this is a stupid idea:

VAT_RATE = 1.19
net = BigDecimal('12.3413')
gross = net * VAT_RATE # oops, gross is now a Float

Do this instead:

VAT_RATE = BigDecimal('1.19')
net = BigDecimal('12.3413')
gross = net * VAT_RATE # gross is now a BigDecimal

ActiveRecord models represent MySQL's DECIMAL columns as BigDecimal attributes. Keep in mind that values assigned to such attributes might be clipped or rounded when the record is saved to the database.

Posted by Henning Koch to makandra dev (2011-04-29 17:16)