Arthur
Arthur

Reputation: 1984

Floating point numbers of Python "float" and PostgreSQL "double precision"

Are Python's "float" type and PostgreSQL's "double precision" type based on the same C implementation? That may not be the real underlying problem here, but anyway, here's what I get when I try to manipulate small numbers in both environments:

On Python (2.7.2 GCC 4.2.1, if that's relevant):

>>> float('1e-310')
1e-310

On PostgreSQL (9.1.1):

postgres# select 1e-310::double precision;
ERROR:  "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" is out of range for type double precision

What I understand is that Python float type "handles" 1e-310 while PostgreSQL double precision type does not. Both Python and PostgreSQL docs on, respectively, "float" and "double precision" types, refer to the IEEE 754 standard, which is supposed to be implemented on "most platforms" (I'm on OS X Lion 10.7.3).

Could anyone explain what's happening here? And give me a solution, I'd like for instance to "reduce" Python precision so I can insert floats in my database through a Django FloatField. (The full use case is that I'm reading figures from a file and then inserting them).

Some (maybe interesting) additional information, in Python:

>>> sys.float_info
sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)
>>> 1e-320.__sizeof__()
24

I really don't get the second one.

Upvotes: 8

Views: 5449

Answers (1)

Raymond Hettinger
Raymond Hettinger

Reputation: 226296

The value float('1e-310') is a denormal number which is outside the usual range of exponents for 53-bit floats (+308 to -308) so it is stored with less precision in order to achieve gradual underflow.

It seems the PostgreSQL has some unresolved issues with denormals: http://archives.postgresql.org/pgsql-hackers/2011-06/msg00885.php

For values near zero, consider rounding them prior to storage in the DB:

>>> round(float('1e-302'), 308)
1e-302
>>> round(float('1e-310'), 308)
0.0

Upvotes: 8

Related Questions