Opened 12 years ago

Closed 11 years ago

#3382 closed (wontfix)

FloatField values get rounded on save()

Reported by: rfugger at gmail dot com Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: Keywords: float rounding
Cc: Triage Stage: Design decision needed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


Django uses the %s format code to insert FloatField values into SQL command strings to send to the database. However, the %s format code rounds floating point numbers to 12 significant digits, which may cause unexpected rounding when the FloatField is configured to store more than 12 digits.

I would have expected Django to use the '%.xf' format code, where x = decimal_places specified for the FloatField in the model definition, which would prevent rounding when saving to the database.

Change History (5)

comment:1 Changed 12 years ago by rfugger at gmail dot com

After further thought, my idea would reduce the ability for people to use their own decimal types. It's fine to let the user be responsible for converting to a string with the desired precision before calling save(). Maybe document somewhere though?

comment:2 Changed 12 years ago by Michael Radziej <mir@…>

Triage Stage: UnreviewedDesign decision needed

comment:3 Changed 12 years ago by adurdin@…

The "%s" used in SQL queries constructed by Python AFAIK are not placeholders for Python %-substitution, but rather placeholders for the DB API. Can you demonstrate that the rounding you mention is actually occurring, and is not due to the database backend?

I have used full-precision floats in Django with MySQL without rounding errors when writing the DecimalField tests (#2365); however I found that SQLite would round some values in the last digit.

comment:4 Changed 12 years ago by Malcolm Tredinnick

I think this is almost impossible to fix perfectly, because it would require checking the field type everywhere we constructed an SQL query to pass to the DB API(s). It's possible to use something like %f in those strings if we had the information, but it would be a really fiddly change to make.

If you'd like to create a patch, we can certainly take a look at it, but I don't think this is a high priority change at the moment.

comment:5 in reply to:  3 Changed 11 years ago by Jacob

Resolution: wontfix
Status: newclosed

adurdin is right -- the %s is actually a dbapi placeholder; the database driver itself is figuring out how to write out the float, so Django has no control over it. Floats will always be imprecise in this way, so if you need exact control like this, use a DecimalField instead.

Note: See TracTickets for help on using tickets.
Back to Top