2008-12-01 8 views
11

Veo referencias conflictivas en Oracles documentation. ¿Hay alguna diferencia entre cómo se almacenan los decimales en los tipos FLOAT y NUMBER en la base de datos?Oracle Floats contra el número

Como recuerdo de C, et al, una flotación tiene limitaciones de precisión que una int no tiene. R.g., para 'float's, 0.1 (Base 10) se aproxima a 0.110011001100110011001101 (Base 2) que equivale aproximadamente a 0.100000001490116119384765625 (Base 10). Sin embargo, para 'int's, 5 (Base 10) es exactamente 101 (Base 2).

por lo que el siguiente no terminará como se esperaba en C:

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

Sin embargo veo que flotan elsewhere in Oracle's documentation se ha definido como un número. Y, como yo lo entiendo, la implementación de Oracle del tipo NUMBER no tiene el mismo problema que el float de C.

Entonces, ¿cuál es la verdadera historia aquí? ¿Se ha desviado Oracle de la norma de lo que espero que ocurra con los flotadores/FLOAT?

(estoy seguro de que es un pez-pedo-en-un-huracán de la diferencia para lo que los voy a utilizar, pero sé que voy a tener preguntas si 0.1 * 10 sale a 1.00000000000000001)

Respuesta

22

BINARY_FLOAT tiendas de Oracle los datos internamente utilizando IEEE 754 representación de coma flotante, como C y muchos otros lenguajes. Cuando los recupera de la base de datos y, por lo general, los almacena en un tipo de datos IEEE 754 en el idioma del host, puede copiar el valor sin transformarlo.

Mientras que el tipo de datos FLOAT de Oracle es un sinónimo para el tipo de datos ANSI SQL NUMERIC, llamado NUMBER en Oracle. Este es un tipo de datos decimales exactos, escalados, que no tiene el comportamiento de redondeo de IEEE 754. Pero si recupera estos valores de la base de datos y los coloca en un flotante C o Java, puede perder precisión durante este paso.

3

El número de Oracle es de hecho una representación de coma flotante decimal (base-10) ... Float es solo un alias para Number y hace exactamente lo mismo.

si desea flotantes binarios (base-2), debe utilizar los tipos de datos BINARY_FLOAT o BINARY_DOUBLE de Oracle.

link text

10

Oracle BINARY_FLOAT y BINARY_DOUBLE son en su mayoría equivalentes al estándar IEEE 754, pero definitivamente no se almacenan internamente en la representación estándar IEEE 754.

Por ejemplo, un BINARY_DOUBLE toma 9 bytes de almacenamiento frente a IEEE 8. También el doble número flotante -3.0 se representa como 3F-F7-FF-FF-FF-FF-FF-FF que si usa IEEE real sería C0-08-00-00-00-00-00-00. Observe que el bit 63 es 0 en la representación de Oracle mientras que es 1 en el IEEE uno (si 's' es el bit de signo, de acuerdo con IEEE, el signo del número es (-1)^s).Ver las muy buenas IEEE 754 calculadoras en http://babbage.cs.qc.cuny.edu/IEEE-754/

Usted puede encontrar fácilmente esto si tiene una columna BINARY__DOUBLE BD en la tabla T con la consulta:

seleccione BD, DUMP (BD) de T

Ahora todo eso es bueno e interesante (tal vez) pero cuando uno trabaja en C y obtiene un valor numérico de Oracle (vinculando una variable a una columna numérica de cualquier tipo), uno normalmente obtiene el resultado en un IEEE real doble como es compatible con C. Ahora, este valor está sujeto a todas las imprecisiones habituales de IEEE.

Si uno quiere hacer una aritmética precisa, puede hacerlo en PL/SQL o utilizando bibliotecas especiales de aritmética precisa.

Por propia explicación de Oracle de sus tipos de datos numéricos ver: http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/datatype.htm#i16209

2

respuesta de Bill sobre FLOAT de Oracle sólo es correcto a la versión tardía (por ejemplo 11i), en Oracle 8i, el documento dice:

Puede especificar números de punto flotante con el formulario explicado en "NUMBER Datatype". Oracle también es compatible con el tipo de datos ANSI FLOAT. Usted puede especificar este tipo de datos utilizando una de estas formas sintácticas:

FLOAT especifica un número de coma flotante con precisión decimal 38, o precisión binaria 126. FLOAT (b) especifica un número de coma flotante con precisión binaria b . La precisión b puede ir de 1 a 126. Para convertir de precisión binaria a decimal, multiplica b por 0.30103. Para convertir de precisión decimal a binaria, multiplique la precisión decimal por 3.32193. El máximo de 126 dígitos de precisión binaria es aproximadamente equivalente a 38 dígitos de precisión decimal.

Suena como una precisión cuádruple (126 precisión binaria). Si no me equivoco, IEEE754 solo requiere b = 2, p = 24 para la precisión simple yp = 53 para la precisión doble. Las diferencias entre 8i y 11i causaron mucha confusión cuando buscaba un plan de conversión entre Oracle y PostgreSQL.

2

Al igual que el PLS_INTEGER se mencionó anteriormente, la BINARY_FLOAT y tipos BINARY_DOUBLE en Oracle uso 10g máquina aritmética y requieren menos espacio de almacenamiento, los cuales los hacen más eficiente que el tipo de número

  • SOLO BINARY_FLOAT y BINARY_DOUBLE apoya NAN valores

- no cálculos precisos

Cuestiones relacionadas