Search code examples
rubyfloating-pointbigdecimal

Why is BigDecimal returning a weird value?


I am writing code that will deal with currencies, charges, etc. I am going to use the BigDecimal class for math and storage, but we ran into something weird with it.

This statement:

1876.8 == BigDecimal('1876.8')

returns false.

If I run those values through a formatting string "%.13f" I get:

"%.20f" % 1876.8 => 1876.8000000000000
"%.20f" % BigDecimal('1876.8') => 1876.8000000000002

Note the extra 2 from the BigDecimal at the last decimal place.

I thought BigDecimal was supposed to counter the inaccuracies of storing real numbers directly in the native floating point of the computer. Where is this 2 coming from?


Solution

  • You are right, BigDecimal should be storing it correctly, my best guess is:

    • BigDecimal is storing the value correctly
    • When passed to a string formatting function, BigDecimal is being cast as a lower precision floating point value, creating the ...02.
    • When compared directly with a float, the float has an extra decimal place far beyond the 20 you see (classic floats can't be compared behavoir).

    Either way, you are unlikely to get accurate results comparing a float to a BigDecimal.