2012-03-04 43 views
6

Loại "phao" của Python và loại "chính xác kép" của PostgreSQL dựa trên cùng một triển khai C? Đó có thể không phải là vấn đề tiềm ẩn thực sự ở đây, nhưng dù sao, đây là những gì tôi nhận được khi tôi cố gắng thao tác các số nhỏ trong cả hai môi trường:Số dấu phẩy động của "phao" và "độ chính xác kép" của Python là

Trên Python (2.7.2 GCC 4.2.1, nếu có liên quan):

>>> 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 

Những gì tôi hiểu là Python kiểu float "xử lý" 1e-310 trong khi PostgreSQL loại chính xác gấp đôi thì không. Cả hai loại PythonPostgreSQL tài liệu trên, tương ứng, "nổi" và "độ chính xác kép", tham khảo tiêu chuẩn IEEE 754, được cho là được triển khai trên "hầu hết nền tảng" (Tôi đang sử dụng OS X Lion 10.7.3) .

Có ai có thể giải thích những gì đang xảy ra ở đây không? Và cho tôi một giải pháp, tôi muốn ví dụ để "giảm" chính xác Python vì vậy tôi có thể chèn nổi trong cơ sở dữ liệu của tôi thông qua một FloatField Django. (Trường hợp sử dụng đầy đủ là tôi đang đọc các số liệu từ một tệp và sau đó chèn chúng).

Một số (có thể thú vị) có thêm thông tin, bằng 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 

tôi thực sự không có được một giây.

+0

tôi suy đoán rằng Postgres được từ chối đưa nó cho bạn bởi vì .1 không thể được biểu diễn chính xác trong nhị phân (cho phần định trị). – bdares

+0

@bdares Tôi không chắc mình hiểu. "chọn 1e-100 :: độ chính xác gấp đôi;" hoạt động tốt trong Postgres; và tôi không nghĩ đây là vấn đề chính xác, mà là một sự chính xác – Arthur

Trả lời

8

Giá trị float ('1e-310') là denormal number nằm ngoài phạm vi thông thường của số mũ cho nổi 53 bit (+308 đến -308) để nó được lưu trữ với độ chính xác thấp hơn .

Có vẻ như PostgreSQL có một số vấn đề chưa được giải quyết với denormals: http://archives.postgresql.org/pgsql-hackers/2011-06/msg00885.php

Đối với giá trị gần bằng không, hãy xem xét làm tròn chúng trước khi lưu trữ trong DB:

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

Cảm ơn! Mát mẻ không có đất của người đàn ông. Tuy nhiên, có một khu vực thậm chí hẹp hơn, nơi giải pháp của bạn không hoạt động: ví dụ: vòng (float ('1e-308'), 308) cho 1e-308 không được chấp nhận bởi postgres. Tôi chỉ đơn giản là đã chọn để làm: nếu abs (ff) Arthur

Các vấn đề liên quan