5

I have table with float column (I'm using MySQL, mysql2 gem, everything standard)

create_table :some_table do |t| 
  t.float  :amount 
end 

I was playing around in console, when i do

a = SomeTable.new
a.amount = 9999.99
a.save!
#9999.99
a.amount
#9999.99
a.reload
a.amount
#9999.99

everything ok

a = SomeTable.new
a.amount = 9999.999
a.save!
#9999.999
a.amount 
#9999.999
a.reload
a.amount
#10000.00

as you see ruby (or rails ) rounds the numbers.

Can someone explain me why is that? ...or is just me ?

4 Answers 4

4

If you want to know all about floats and why they have rounding errors, see What Every Computer Scientist Should Know About Floating-Point Arithmetic.

If you are tying to do currency calculations, don't use float! Use a fixed point data type. If you use rails migrations, the decimal type is what you want as described here.

Sign up to request clarification or add additional context in comments.

2 Comments

add_column :something, :amount, :decimal, :precision => 15, :scale => 4
Yes, floating point numbers have rounding errors. However, IEEE floats have no problem accurately representing 9999.999 (or for that matter 9999.99999999999), so it isn't exactly accurate to say that rounding errors are causing this problem. As far as I can tell from testing it, this is an issue with the mysql2 adapter.
4

Accepted answer is correct in general (and using decimal instead of float will work around the problem).

However, there's a deeper issue here.

The mysql2 driver isn't specifying the precision it wants mysql to return, so the database is returning truncated results.

You can force mysql to return the full precision by multiplying the amount by a float.

class SomeTable
  default_scope -> { select("some_tables.*, amount * 1.0000000000000000 as amount")}
end

a = SomeTable.new
a.amount = 9999.999
a.save!
#9999.999
SomeTable.last.amount 
#9999.999
SomeTable.unscoped.last.amount
#10000.00

1 Comment

If it makes you feel any better, at least it's not truncating to zero by default. web.archive.org/web/20070626050750/http://www.fluidscape.co.nz/…
1

The MySQL documentation describes float as an "approximate numeric data type"...probably not good for storing money values. Try defining "amount" as a decimal, instead.

Comments

0

It looks like the database is the one doing the number changing.

I believe what's happening here is that the MSSQL table being created has a precision of only two digits below the decimal point (or has a hard time storing precision in decimal form), so anything put in after that is getting rounded by the database, but not the code.

1 Comment

yeah I guess that's it I'm only annoyed because its rounding f.e. 4567.7889 to 4567.8 and not 4567.789 (or 4567.79) I'm loosing precision

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.