Financial app - decimal to float conversion problem


#1

I’m having problems with using Rails for a financial application: the
database stores financial fields as decimal, but ActiveRecord converts
these to float - so I get the rounding errors you’d expect
(http://www.mindprod.com/jgloss/floatingpoint.html).

This has come up recently, and the recommended fix seems to be to be
Tobi Luetke’s ‘money’ gem
(http://article.gmane.org/gmane.comp.lang.ruby.rails/46632/match=money+bigdecimal)
but this won’t work for me: I’ve inherited the (SQLServer) database, and
financial fields are defined as decimal: I can’t insist on changing
everything to integer values in cents.

What seems to be needed is changing the Ruby type mapping, which seems
to be a ‘good idea’ that’s come up before
(http://article.gmane.org/gmane.comp.lang.ruby.rails/713) but hasn’t
made it into Rails, at least not 1.0. Have people tried and given up?
What would be involved?

I’ve had a poke around abstract_adapter.rb and sqlserver_adapter.rb and
can see some places to hack, but haven’t followed through the
implications. I don’t mind adding a dependency on bigdecimal, even if
only the resulting fix could only be distributed as a plugin rather than
a patch to the Rails trunk.

Any help, hacks or workarounds much appreciated - if I can’t solve this
problem in Rails, my chances of selling Ruby and Rails internally more
or less vanish…

thanks

Stuart


#2

On 15/02/06, Stuart J. removed_email_address@domain.invalid wrote:

Any help, hacks or workarounds much appreciated - if I can’t solve this
problem in Rails, my chances of selling Ruby and Rails internally more
or less vanish…

To avoid floating point conversion, I multiply currency values before
calculation by 100 (for 2 decimal places), perform my operation, and
finally divide by 100. Perhaps this will work for you as well?

Cheers,
Hasan D. removed_email_address@domain.invalid


#3

A new ruby library is being developed on rubyforge.org,
which can handle numbers of the type stored in databases, with
a fixed number of digits after the decimal point. It is called
long-decimal, can be installed with
gem install long-decimal
and should be stable if you want to use +, -, *, sqrt and /.
Beyond the functionality of similar classes of Java it can also
do some transcendental functions like exp and log, which are not
quite as stable now, so that the whole library is still called alpha.

Maybe it would be a good idea to use exactly this type for active
records when mapping decimals of databases to ruby.

Best regards,

Karl