views:

124

answers:

2

Is the BigDecimal class broken? It seems like the following should never, ever occur: Note that a.to_f != a.to_s.to_f

a.class => BigDecimal

a.to_f => 18658.1072928

a.to_s => "10865.81072928"

b.class => BigDecimal

b.to_f => 10000.0

b.to_s => "10000.0"

(a - b).to_f => 865.81072928

a.to_f - b.to_f => 8658.1072928

Any ideas as to what might be going wrong? We are running ruby 1.8.7p72 on our servers and 1.8.7p173 on our local machines.

+1  A: 

As the docs say:

to_f:

Returns a new Float object having approximately the same value as the BigDecimal number. Normal accuracy limits and built-in errors of binary Float arithmetic apply.

That means that Float in ruby behaves just like a float everywhere: http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

Not every number is representable by a Float. In such cases the number is rounded.

Tomas Markauskas
a.to_f => 18658.1072928a.to_s => "10865.81072928"I don't think we can blame a difference of almost 8000 on roundoff error...
Chris Bisignani
You're right. I also tested it on my local machine (I'm running 1.8.7p173 too) and results are different: >> a = BigDecimal.new('10865.81072928') => #<BigDecimal:101416890,'0.1865810729 28E5',16(20)> >> a.to_s => "0.186581072928E5" >> a.to_f => 18658.1072928No idea why...
Tomas Markauskas
A: 

If you're running Mac OS X 10.6.3 then this might be an explanation: http://www.abletech.co.nz/2010/03/osx-10-6-3-installs-new-ruby-with-faulty-bigdecimal/

To get rid of the problem you could use RVM.

Tomas Markauskas