Odd BigDecimal Utils Behavior With Float#to_d

Some instances that use the bigdecimal/util Float#to_d method create odd precisions and unequal instances For example:

BigDecimal.new('65.09') == 65.09.to_d   # => true
BigDecimal.new('65.10') == 65.10.to_d   # => false
BigDecimal.new('65.11') == 65.11.to_d   # => true
65.10.to_d.to_s('F')  # => "65.09999999999999"

I can consistently see this in Ruby 1.9/2.0 on a few tested platforms and wonder if this might be considered a bug?

https://gist.github.com/4630660

In the context of Rails/ActiveRecord, I noticed that the Oracle adapter uses the ActiveRecord’s ConnectionAdapters::Column.value_to_decimal(value) method in which it checks for value.respond_to?(:to_d). In Oracle’s case, the value it passes to that method is a float and hence ~10% of floats fail that #to_d equality test and return what looks to me to be bad data, especially when formatted to a string.

I’ve heard from Aaron before that ActiveRecord is kind of optimized for raw connections that return strings for all their data types, so this is not likely to affect the 3 core adapters. In fact, I could not get any tests to fail. However, it did make me wonder if there is (1) some interest in commenting on the oddities and (2) thoughts on making value_to_decimal(value) take an optional precision argument to account for the random behavior?

  • Thanks,

Ken