Alex Rivera | Logout

Ruby: Why is 1.025.round(2) rounded to 1.02?

Asked 2011-09-29T08:38:59.280
12

As far as I understand the .round()-functionality in ruby rounds decimals upwards where the last significant number is 5?

For example 1.5.round(0) # => 2 (OK)

but why does 1.025.round(2) # => 1.02, and not 1.03 as I would expect?

irb(main):037:0> 1.025.round(2)
=> 1.02

What can I do to go around this?

Edit
Report

1 Answer

22

This has nothing to do with the last digit being 5 and everything to do with conversion of a decimal value to a double precision floating point value.

http://en.wikipedia.org/wiki/Double_precision_floating-point_format

Basically, the decimal number has to be represented in limited binary format which can only approximate certain decimal values, leading to loss of precision. This can cause some weird behavior, as you have seen.

Best to explain this by showing you... Marshal.dump(1.025) dumps the Float value and shows the value a bit closer to what it really is: 1.0249999999999999. 1.025.to_r will provide you with the fraction which represents the binary value. You can use the arbitrarily precise decimal library, BigDecimal to convert this:

ruby-1.9.2-p180 :060 > (BigDecimal.new("2308094809027379.0") / BigDecimal.new("2251799813685248.0")).to_s('F')
=> "1.024999999999999911182158029987476766"

When certain decimals are converted to this "approximate" binary number format they will be represented differently, possibly more precisely. So, you might have noticed that 1.085.round(2) results in 1.09 as you'd expect.

This lack of precision with floating point math means it's never, ever appropiate to use floating point values for currency calculations, or even as temporary containers for money values. Arbitrary precision data types should be used at all times for anything involving money.

As a former developer for an extremely large financial company I was constantly shocked by how rarely this advice is heeded and how common the use of floats or doubles is in financial software. Most programmers in that industry I have talked to are not aware that floats and doubles should never store money values. So, don't feel like you ar

answered 2011-09-29T09:20:12.520

Your Answer