On Feb 8, 2008, at 8:35 AM, Rodrigo Kochenburger wrote: > On Feb 7, 10:42 pm, Rob Biedenharn <R... / AgileConsultingLLC.com> > wrote: >> On Feb 7, 2008, at 6:59 PM, Henry Jones wrote: >>> Rob Biedenharn wrote: >>>> On Feb 7, 2008, at 5:26 PM, Henry Jones wrote: >> >>>>> BigDecimal.new('15.25').to_f == 15.25.to_f also returns false. >> >>>>> Substracting both values returns 1.7763... e-015 >> >>>>> This is on ruby 1.8.6, Win32. >> >>>>> I'm a comp. engineer, so I know it's ultimately related to the >>>>> binary >>>>> value of 15.25 which cannot be precisely represented (without an >>>>> infinite number of bits) , but I'm still amazed that such a simple >>>>> comparison with a literal value should fail... >> >>>> 15.25 in decimal >>>> is exactly >>>> 1111.01 in binary >> >>>> Seems like a finite number of bits to me ;-) However, the >>>> construction of 15.25 as a literal is likely something roughly >>>> (1*10^1 >>>> + 5*10^0) + (2*10^-1 + 5*10^-2) and those intermediate fractional >>>> terms are problematic. >> >>>> Hey, this is Ruby! Roll your own with === >> >>>> irb> class Float >>>> irb> def ===(other,eps=0.000000001) >>>> irb> (self - other.to_f).abs < eps >>>> irb> end >>>> irb> end >>>> => nil >>>> irb> require 'bigdecimal' >>>> => true >>>> irb> 15.25 == BigDecimal.new("15.25") >>>> => false >>>> irb> 15.25 === BigDecimal.new("15.25") >>>> => true >> >>>> Of course, you'd have to add a similar BigDecimal#=== to get >>>> symmetry. >> >>>> -Rob >> >>>> Rob Biedenharn http://agileconsultingllc.com >>>> R... / AgileConsultingLLC.com >> >>> Apparently the problem lies with BigDecimal, and not the literal >>> value : >> >>> "%.30f" % 15.25 >>> will print : "15.250000000000000000000000000000" (not copy pasted, >>> don't count the zeros =) ) >> >>> but >>> "%.30f" % BigDecimal("15.25") >>> will print : "15.250000000000002000000000000000" (notice the '2' in >>> there) >>> -- >>> Posted viahttp://www.ruby-forum.com/. >> >> Well, now you're pulling in the BigDecimal#to_f which isn't so much a >> problem in BigDecimal as it is the same limitation of a Float. >> >> irb> "%.30f" % 15.25 >> => "15.250000000000000000000000000000" >> irb> require 'bigdecimal' >> => [] >> irb> "%.30f" % BigDecimal.new('15.25') >> => "15.250000000000001776356839400250" >> irb> "%.30f" % BigDecimal.new('15.25').to_f >> => "15.250000000000001776356839400250" >> >> And that just gets back to the problem of building the number up from >> its decimal pieces: >> >> irb> "%.30f" % BigDecimal.new('0.05') >> => "0.050000000000000002775557561563" >> irb> "%.30f" % BigDecimal.new('0.2') >> => "0.200000000000000011102230246252" >> irb> "%.30f" % BigDecimal.new('5.0') >> => "5.000000000000000000000000000000" >> irb> "%.30f" % BigDecimal.new('10.0') >> => "10.000000000000000000000000000000" >> >> (and your '2' is off by two places ;-) >> >> -Rob >> >> Rob Biedenharn http://agileconsultingllc.com >> R... / AgileConsultingLLC.com > > I agree this is a problem with BigDecimal. The problem is not with the > floating point representation: > >>> "%.30f" % BigDecimal.new("15.00") > => "15.000000000000001776356839400250" >>> "%.30f" % BigDecimal.new("15.00").to_f > => "15.000000000000001776356839400250" >>> "%.30f" % 15.00 > => "15.000000000000000000000000000000" > > Also, it looks like it happens on 64bits machines only. > > This is from a 32bits: > >>> "%.30f" % BigDecimal.new("15.00") > => "15.000000000000000000000000000000" >>> "%.30f" % BigDecimal.new("15.00").to_f > => "15.000000000000000000000000000000" >>> "%.30f" % 15.00 > => "15.000000000000000000000000000000" > > Anybody familiar with the BigDecimal internals could check this, > please? Well, my machine is only 32bits. You shouldn't have a problem with small integers. It's when you attempt to represent some fractional decimal values in binary. Now, if you wanted to say something about the apparent difference between BigDecimal#to_f and String#to_f, then you could be onto something. irb> require 'bigdecimal' => true irb> "%.30f" % (61.0/4.0) => "15.250000000000000000000000000000" irb> (61.0/4.0) == 15.25 => true irb> "%.30f" % 15.25 => "15.250000000000000000000000000000" irb> "%.30f" % BigDecimal.new("15.25") => "15.250000000000001776356839400250" irb> "%.30f" % BigDecimal.new("15.25").to_s.to_f => "15.250000000000000000000000000000" -Rob Rob Biedenharn http://agileconsultingllc.com Rob / AgileConsultingLLC.com