2008-12-01 32 views
11

Tôi đang xem các tham chiếu xung đột trong Oracles documentation. Có sự khác biệt nào giữa số thập phân được lưu trữ trong FLOAT và NUMBER loại trong cơ sở dữ liệu không?Số nổi Oracle vs Số

Khi tôi nhớ lại từ C, et al, phao có các giới hạn chính xác mà một int không có. Ví dụ: Đối với 'phao', 0,1 (Cơ sở 10) xấp xỉ là 0,110011001100110011001101 (Cơ sở 2) tương đương với một cái gì đó giống như 0,100000001490116119384765625 (Cơ sở 10). Tuy nhiên, đối với 'int's, 5 (Base 10) là chính xác 101 (Base 2).

Đó là lý do sau đây sẽ không chấm dứt như mong đợi trong C:

float i; 
i = 0; 
for (i=0; i != 10;) 
{ 
    i += 0.1 
} 

Tuy nhiên tôi thấy elsewhere in Oracle's documentation mà phao đã được định nghĩa là một số. Và như tôi đã hiểu, việc triển khai thực hiện kiểu số NUMBER của Oracle không chạy cùng một vấn đề với float của C.

Vậy, câu chuyện có thật ở đây là gì? Có Oracle lệch khỏi định mức của những gì tôi mong đợi xảy ra với phao nổi/FLOAT?

(Tôi chắc chắn đó là một con ong-fart-in-a-hurricane của sự khác biệt cho những gì tôi sẽ sử dụng chúng cho, nhưng tôi biết tôi sẽ có câu hỏi nếu 0.1 * 10 đi ra đến 1.00000000000000001)

Trả lời

22

Oracle BINARY_FLOAT lưu trữ dữ liệu trong nội bộ sử dụng IEEE 754 đại diện dấu chấm động, giống như C và nhiều ngôn ngữ khác làm. Khi bạn tìm nạp chúng từ cơ sở dữ liệu, và thường lưu trữ chúng trong một kiểu dữ liệu IEEE 754 trong ngôn ngữ máy chủ, nó có thể sao chép giá trị mà không cần chuyển đổi nó.

Trong khi kiểu dữ liệu FLOAT của Oracle là một từ đồng nghĩa cho loại dữ liệu ANSI SQL NUMERIC, được gọi là NUMBER trong Oracle. Đây là một số chính xác, một kiểu dữ liệu thập phân được chia tỷ lệ không có hành vi làm tròn của IEEE 754. Nhưng nếu bạn lấy các giá trị này từ cơ sở dữ liệu và đặt chúng vào một float C hoặc Java, bạn có thể mất độ chính xác trong bước này.

3

Số của Oracle thực chất là một biểu diễn dấu phẩy động thập phân (cơ sở-10) ... Float chỉ là bí danh cho Số và thực hiện chính xác điều tương tự.

nếu bạn muốn các loại nhị phân (base-2) nổi, bạn cần sử dụng các kiểu dữ liệu BINARY_FLOAT hoặc BINARY_DOUBLE của Oracle.

link text

10

Oracle BINARY_FLOAT và BINARY_DOUBLE chủ yếu tương đương với chuẩn IEEE 754 nhưng chúng không được lưu trữ nội bộ trong tiêu chuẩn IEEE 754.

Ví dụ, BINARY_DOUBLE nhận 9 byte dung lượng lưu trữ so với IEEE 8. Ngoài ra, số nổi kép -3.0 được biểu diễn là 3F-F7-FF-FF-FF-FF-FF-FF, nếu bạn sử dụng IEEE thực sẽ là C0-08-00-00-00-00-00-00. Chú ý rằng bit 63 là 0 trong biểu diễn Oracle trong khi nó là 1 trong IEEE (nếu là 'là bit dấu, theo IEEE, dấu của số là (-1)^s).Xem rất tốt IEEE 754 máy tính tại http://babbage.cs.qc.cuny.edu/IEEE-754/

Bạn có thể dễ dàng tìm thấy điều này nếu bạn có một cột BINARY__DOUBLE BD trong bảng T với truy vấn:

chọn BD, DUMP (BD) từ T

Bây giờ tất cả điều đó là tốt và thú vị (có thể) nhưng khi một công trình trong C và nhận được một giá trị số từ Oracle (bằng cách liên kết một biến đến một cột số của bất kỳ loại nào), một thường nhận được kết quả trong một IEEE thực gấp đôi như được hỗ trợ bởi C. Bây giờ giá trị này là tùy thuộc vào tất cả các thông tin không chính xác của IEEE thông thường.

Nếu người ta muốn làm số học chính xác, người ta có thể làm điều đó trong PL/SQL hoặc sử dụng các thư viện C số học chính xác đặc biệt.

Đối với lời giải thích riêng của Oracle của các loại dữ liệu số họ nhìn thấy: http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/datatype.htm#i16209

2

câu trả lời của Bill về FLOAT của Oracle là chỉ đúng với phiên bản cuối (nói 11i), trong Oracle 8i, tài liệu nói:

Bạn có thể chỉ định các số dấu phẩy động có dạng được thảo luận trong "NUMBER Kiểu dữ liệu". Oracle cũng hỗ trợ FLOAT kiểu dữ liệu ANSI. Bạn có thể chỉ định kiểu dữ liệu này sử dụng một trong các hình thức cú pháp:

FLOAT quy định cụ thể một số dấu chấm động với độ chính xác thập phân 38, hoặc chính xác nhị phân 126. FLOAT (b) quy định cụ thể một số dấu chấm động với độ chính xác nhị phân b . Độ chính xác b có thể nằm trong khoảng từ 1 đến 126. Để chuyển đổi từ nhị phân sang độ chính xác thập phân, nhân b với 0,30103. Để chuyển đổi từ thập phân sang độ chính xác nhị phân, nhân số thập phân chính xác với 3,32193. Tối đa 126 chữ số có độ chính xác nhị phân là tương đương với 38 chữ số có độ chính xác thập phân.

Có vẻ như độ chính xác gấp bốn lần (độ chính xác nhị phân 126). Nếu tôi không nhầm, IEEE754 chỉ yêu cầu b = 2, p = 24 cho độ chính xác đơn và p = 53 cho độ chính xác gấp đôi. Sự khác biệt giữa 8i và 11i gây ra rất nhiều sự nhầm lẫn khi tôi đang xem xét một kế hoạch chuyển đổi giữa Oracle và PostgreSQL.

2

Giống như PLS_INTEGER đề cập trước đây, các BINARY_FLOAT và các loại BINARY_DOUBLE trong Oracle sử dụng 10g máy số học và đòi hỏi không gian lưu trữ ít hơn, cả hai đều làm cho họ hiệu quả hơn các loại SỐ

  • CHỈ BINARY_FLOAT và BINARY_DOUBLE hỗ trợ NAN đánh giá cao

- không tính toán chính xác