2008-12-01 11 views
11

Vedo riferimenti in conflitto in Oracles documentation. C'è qualche differenza tra il modo in cui i decimali sono memorizzati in un FLOAT e in NUMBER tipi nel database?Oracle Floats vs Number

Come ricordo da C, et al, un float ha limitazioni di precisione che un int non ha. R.g. Per 'float', 0.1 (Base 10) è approssimato come 0.110011001100110011001101 (Base 2) che equivale a qualcosa di simile a 0.100000001490116119384765625 (Base 10). Tuttavia, per 'int's, 5 (Base 10) è esattamente 101 (Base 2).

motivo per cui il seguente non terminerà come previsto in C:

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

Tuttavia vedo elsewhere in Oracle's documentation che galleggiano è stato definito come un numero. E a quanto ho capito, l'implementazione di Oracle del tipo NUMBER non ha lo stesso problema del float di C.

Quindi, qual è la vera storia qui? Oracle ha deviato dalla norma di ciò che mi aspetto di accadere con float/FLOATs?

(Sono sicuro che è un vortice-in-a-un-uragano di differenza per quello che userò per loro, ma so che avrò domande se 0.1 * 10 uscirà a 1.00000000000000001

risposta

22

di Oracle BINARY_FLOAT memorizza i dati internamente utilizzando IEEE 754 rappresentazione in virgola mobile, come il C e molte altre lingue fanno. Quando li si preleva dal database e in genere li si archivia in un tipo di dati IEEE 754 nella lingua host, è in grado di copiare il valore senza trasformarlo.

Considerando che il tipo di dati Oracle FLOAT è un sinonimo per il tipo di dati ANSI SQL NUMERIC, denominato NUMBER in Oracle. Questo è un tipo numerico esatto, un tipo di dati decimale in scala che non ha il comportamento di arrotondamento di IEEE 754. Ma se si recuperano questi valori dal database e li si inserisce in un float C o Java, è possibile perdere precisione durante questo passaggio.

3

Oracle's Number è in realtà una rappresentazione in virgola mobile decimale (base-10) ... Float è solo un alias per Number e fa esattamente la stessa cosa.

se si desidera il codice binario (base-2), è necessario utilizzare i tipi di dati BINARY_FLOAT o BINARY_DOUBLE di Oracle.

link text

10

Oracle BINARY_FLOAT e BINARY_DOUBLE sono per lo più equivalenti allo standard IEEE 754 ma non sono memorizzati internamente nella rappresentazione IEEE 754 standard.

Ad esempio, un BINARY_DOUBLE richiede 9 byte di memoria rispetto a IEEE 8. Anche il doppio numero floating -3.0 è rappresentato come 3F-F7-FF-FF-FF-FF-FF-FF che se si utilizza IEEE reale sarebbe C0-08-00-00-00-00-00-00. Si noti che il bit 63 è 0 nella rappresentazione Oracle mentre è 1 in IEEE (se 's' è il bit di segno, secondo IEEE, il segno del numero è (-1)^s).Vedi le ottime IEEE 754 calcolatrici a http://babbage.cs.qc.cuny.edu/IEEE-754/

Per la ricerca di questo se si dispone di una colonna BINARY__DOUBLE BD nella tabella T con la query:

selezionare BD, dump (BD) da T

Ora tutto ciò è valido e interessante (forse) ma quando si lavora in C e si ottiene un valore numerico da Oracle (legando una variabile a una colonna numerica di qualsiasi tipo), si ottiene in genere un IEEE reale il doppio è supportato da C. Ora questo valore è soggetto a tutte le abituali imprecisioni IEEE.

Se si desidera eseguire l'aritmetica precisa, è possibile farlo in PL/SQL o utilizzando speciali librerie C aritmetiche precise.

Per la spiegazione di Oracle dei loro tipi di dati numerici si veda: http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/datatype.htm#i16209

2

la risposta di Bill su FLOAT di Oracle è corretto solo per la versione in ritardo (diciamo 11i), in Oracle 8i, dice il documento:

È possibile specificare numeri in virgola mobile con il modulo discusso in "NUMBER Tipo dati". Oracle supporta anche il tipo di dati ANSI FLOAT. È possibile specificare questo tipo di dati utilizzando una di queste forme sintattiche:

FLOAT specifica un numero a virgola mobile con precisione decimale 38, o precisione binaria 126. FLOAT (b) specifica un numero a virgola mobile con precisione binario b . La precisione b può variare da 1 a 126. Per convertire da binario a decimale, moltiplicare b per 0,30103. Per convertire da precisione decimale a binario, moltiplicare la precisione decimale di 3.32193. Il massimo di 126 cifre di precisione binaria è pari a equivalenti a circa 38 cifre di precisione decimale.

Suona come una precisione quadrupla (precisione binaria 126). Se non sbaglio, IEEE754 richiede solo b = 2, p = 24 per precisione singola e p = 53 per precisione doppia. Le differenze tra 8i e 11i hanno causato molta confusione quando stavo esaminando un piano di conversione tra Oracle e PostgreSQL.

2

Come il PLS_INTEGER accennato in precedenza, il BINARY_FLOAT e tipi BINARY_DOUBLE in Oracle uso 10g macchina aritmetica e richiedono meno spazio di archiviazione, entrambi i quali li rendono più efficiente che il tipo di numero

  • SOLO BINARY_FLOAT e BINARY_DOUBLE supporta NAN valori

- non calcoli precisi