Code

Opened 7 years ago

Closed 6 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: UI/UX:

Description

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.

Attachments (0)

Change History (5)

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

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

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 7 years ago by Michael Radziej <mir@…>

  • Triage Stage changed from Unreviewed to Design decision needed

comment:3 follow-up: Changed 7 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 7 years ago by mtredinnick

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 6 years ago by jacob

  • Resolution set to wontfix
  • Status changed from new to closed

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.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.