2012-03-04 4 views
6

Являются ли типы «float» Python и тип «двойной точности» PostgreSQL на основе одной и той же реализации C? Это не может быть реальной основной проблемы здесь, но в любом случае, вот что я получаю, когда я пытаюсь манипулировать небольшое количество в обеих средах:Числа с плавающей запятой «float» Python и «двойная точность» PostgreSQL

на Python (2.7.2 GCC 4.2.1, если это уместно):

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

в PostgreSQL (9.1.1):

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

Я понимаю, что Python типа с плавающей запятой "обрабатывает" 1е-310 в то время как PostgreSQL двойной точности типа нет. Оба форматаи PostgreSQL, соответственно, типа «float» и «double precision», относятся к стандарту IEEE 754, который предполагается реализовать на «большинстве платформ» (я на OS X Lion 10.7.3) ,

Может ли кто-нибудь объяснить, что здесь происходит? И дайте мне решение, я хотел бы, например, «уменьшить» точность Python, чтобы я мог вставлять поплавки в свою базу данных через Django FloatField. (Полный вариант использования - это то, что я читаю данные из файла, а затем вставляю их).

Некоторые из них (возможно, интересно) дополнительной информации, в 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 

Я действительно не получить вторую.

+0

Я бы предположить, что Postgres отказывается дайте это вам, потому что .1 невозможно представить точно в двоичном (для мантиссы). – bdares

+0

@bdares Я не уверен, что понимаю. "select 1e-100 :: double precision;" отлично работает в Postgres; и я не думаю, что это вопрос точности, а скорее точный – Arthur

ответ

8

Значение float ('1e-310') представляет собой denormal number, который находится за пределами обычного диапазона показателей для 53-битных поплавков (от +308 до -308), поэтому он хранится с меньшей точностью, чтобы добиться постепенного снижения ,

Кажется, PostgreSQL имеет некоторые нерешенные проблемы с денормализованных чисел: http://archives.postgresql.org/pgsql-hackers/2011-06/msg00885.php

Для значений, близких к нулю, рассмотреть округлением их до хранения в БД:

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

Спасибо! Прохладный ничейная земля. Однако есть еще более узкий регион, где ваше решение не работает: например, round (float ('1e-308'), 308) дает 1e-308, который не принимается postgres. Я просто решил сделать: if abs (ff) Arthur

Смежные вопросы