2012-03-04 35 views
6

¿El tipo "float" de Python y el tipo "double precision" de PostgreSQL se basan en la misma implementación C? Puede que no sea el verdadero problema subyacente aquí, pero de todos modos, esto es lo que me sale cuando intento de manipular pequeñas cantidades en ambos ambientes:Números flotantes de Python "float" y PostgreSQL "double precision"

En Python (GCC 2.7.2 4.2.1, si es relevante):

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

En PostgreSQL (9.1.1):

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

Lo que entiendo es que Python tipo float "maneja" 1e-310, mientras que PostgreSQL tipo de doble precisión no lo hace. Tanto Python como PostgreSQL documentos, respectivamente, tipos "flotante" y "precisión doble", consulte el estándar IEEE 754, que se supone debe implementarse en "la mayoría de las plataformas" (estoy en OS X Lion 10.7.3) .

¿Alguien podría explicar lo que está sucediendo aquí? Y dame una solución, me gustaría, por ejemplo, "reducir" la precisión de Python para poder insertar flotadores en mi base de datos a través de Django FloatField. (El caso de uso completo es que estoy leyendo cifras de un archivo y luego las inserto).

Algunos (tal vez interesante) información adicional, en 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 

realmente no llegar el segundo.

+0

me gustaría especular que se niega a Postgres se lo da porque .1 no se puede representar exactamente en binario (para la mantisa). – bdares

+0

@bdares No estoy seguro de entender. "seleccione 1e-100 :: precisión doble"; funciona bien en Postgres; y no creo que esto sea un problema de exactitud, sino más bien uno de precisión – Arthur

Respuesta

8

El valor flotador ('1e-310') es un denormal number que está fuera de la gama habitual de exponentes para flotadores 53 bits (308 a -308) por lo que se almacena con menos precisión a fin de lograr underflow gradual .

Parece PostgreSQL tiene algunos problemas no resueltos con denormals: http://archives.postgresql.org/pgsql-hackers/2011-06/msg00885.php

Para valores cercanos a cero, considerarlos redondeo antes de su almacenamiento en la base de datos:

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

¡Gracias! No enfría la tierra de nadie. Sin embargo, hay una región aún más limitada donde su solución no funciona: p. round (float ('1e-308'), 308) da 1e-308 que no es aceptado por postgres. Simplemente elegí hacer: si abs (ff) Arthur

Cuestiones relacionadas