2012-03-04 15 views
6

Czy typ" float "Pythona i" podwójna precyzja "PostgreSQL opierają się na tej samej implementacji C? To nie może być prawdziwe podstawowy problem tutaj, ale w każdym razie, oto co mam przy próbie manipulowania małych liczb w obu środowiskach:Liczba zmiennoprzecinkowa "float" Pythona i "podwójna precyzja" PostgreSQL "

na Python (2.7.2 GCC 4.2.1, jeśli jest to stosowne):

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

Na PostgreSQL (9.1.1):

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

Co rozumiem, jest to, że Python typu float "uchwyty" 1E-310 podczas PostgreSQL rodzaj podwójnej precyzji nie. Zarówno Python, jak i PostgreSQL dokumentują odpowiednio typy "float" i "double precision", odnoszą się do standardu IEEE 754, który ma być implementowany na "większości platform" (jestem na OS X Lion 10.7.3) .

Czy ktoś może wyjaśnić, co się tutaj dzieje? I daj mi rozwiązanie, chciałbym na przykład "zmniejszyć" precyzję Pythona, aby móc wstawiać pływaki do mojej bazy danych poprzez Django FloatField. (W przypadku pełnego użycia czytam dane z pliku, a następnie wstawiam je).

Niektóre (może być interesujące) Informacje dodatkowe, w Pythonie:

>>> 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 naprawdę nie dostać drugi.

+0

chciałbym spekulować, że Postgres odmawia daj ci to, ponieważ .1 nie można dokładnie przedstawić w postaci binarnej (dla mantysy). – bdares

+0

@bdares Nie jestem pewien, czy rozumiem. "wybierz 1e-100 :: podwójna precyzja;" działa dobrze w Postgres; i nie sądzę, że jest to kwestia dokładności, ale raczej precyzja. – Arthur

Odpowiedz

8

Wartość zmiennoprzecinkowa ("1e-310") to denormal number, która znajduje się poza zwykłym zakresem wykładników dla 53-bitowych zmiennoprzecinkowych (+308 do -308), więc jest przechowywana z mniejszą dokładnością w celu osiągnięcia stopniowego niedomiaru .

Wydaje się, że PostgreSQL ma pewne nierozwiązane problemy z denormals: http://archives.postgresql.org/pgsql-hackers/2011-06/msg00885.php

dla wartości bliskie zeru, zaokrąglając je rozważyć przed przechowywaniem w DB:

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

Dziękuję! Chłodny ziemię niczyjej. Istnieje jednak węższy region, w którym Twoje rozwiązanie nie działa: np. round (float ('1e-308'), 308) daje 1e-308, który nie jest akceptowany przez postgres. Po prostu zdecydowałem się zrobić: if abs (ff) Arthur

Powiązane problemy