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
>> Rob / 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 via http://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
Rob / AgileConsultingLLC.com