Question

Des références contradictoires apparaissent dans Documentation d'Oracles . Existe-t-il une différence entre la manière dont les décimales sont stockées dans un FLOAT et les types NUMBER dans la base de données?

Si je me souviens de C, et al, un float a des limites de précision qu'un int ne possède pas. R., pour 'float's, 0.1 (Base 10) est approximativement 0.110011001100110011001101 (Base 2), ce qui équivaut à quelque chose comme 0.100000001490116119384765625 (Base 10). Cependant, pour 'int's, 5 (Base 10) est exactement 101 (Base 2).

C’est pourquoi les éléments suivants ne se terminent pas comme prévu dans C:

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

Cependant, je vois ailleurs dans la documentation d'Oracle que FLOAT a été défini en tant que NUMBER. Et si je comprends bien, l’implémentation du type NUMBER par Oracle ne rencontre pas le même problème que le float de C.

Alors, quelle est la vraie histoire ici? Oracle at-il dévié de la norme de ce que j’attendais avec les flotteurs / FLOAT?

(Je suis sûr que c'est une différence pour ce que je vais utiliser, mais je sais que je vais avoir des questions si 0,1 * 10 est égal à 1,00000000000000001)

Était-ce utile?

La solution

Le BINARY_FLOAT d'Oracle stocke les données en interne à l'aide de la représentation à virgule flottante IEEE 754, comme le font C et de nombreux autres langages. Lorsque vous les récupérez dans la base de données et que vous les stockez généralement dans un type de données IEEE 754 dans le langage hôte, il est capable de copier la valeur sans la transformer.

Alors que le type de données FLOAT d’Oracle est un synonyme du type de données ANSI SQL NUMERIC, appelé NUMBER dans Oracle. Il s'agit d'un type de données numérique décimal mis à l'échelle qui ne présente pas le comportement d'arrondi de IEEE 754. Toutefois, si vous extrayez ces valeurs de la base de données et les mettez dans un float C ou Java, vous pouvez perdre de la précision au cours de cette étape.

Autres conseils

Les Oracle BINARY_FLOAT et BINARY_DOUBLE sont généralement équivalents au standard IEEE 754, mais ils ne sont définitivement pas stockés en interne dans la représentation standard IEEE 754.

Par exemple, un BINARY_DOUBLE prend 9 octets de stockage contre 8 pour IEEE. Le nombre double flottant -3.0 est également représenté par 3F-F7-FF-FF-FF-FF-FF qui, si vous utilisiez de véritables IEEE être C0-08-00-00-00-00-00-00. Notez que le bit 63 est 0 dans la représentation Oracle alors qu'il est 1 dans celui IEEE (si "s" est le bit de signe, selon IEEE, le signe du nombre est (-1) ^ s). Voir les très bonnes calculatrices IEEE 754 à l'adresse http: //babbage.cs.qc.cuny. edu / IEEE-754 /

Vous pouvez facilement le trouver si vous avez une colonne BINARY__DOUBLE BD dans la table T avec la requête:

  

sélectionnez BD, DUMP (BD) parmi T

Maintenant tout cela est beau et intéressant (peut-être) mais quand on travaille en C et obtient une valeur numérique d'Oracle (en liant une variable à une colonne numérique de quelque type que ce soit), on obtient généralement le résultat dans un véritable IEEE double comme est supporté par C. Maintenant, cette valeur est sujette à toutes les inexactitudes IEEE habituelles.

Si vous voulez faire de l'arithmétique précise, vous pouvez le faire en PL / SQL ou en utilisant des bibliothèques C spéciales à l'arithmétique précise.

Pour la propre explication d'Oracle sur leurs types de données numériques, voir: http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/datatype.htm#i16209

Le numéro d’Oracle est en fait une représentation décimale à virgule flottante (base-10) ... Float est juste un alias pour Number et fait exactement la même chose.

si vous voulez des valeurs flottantes binaires (base 2), vous devez utiliser les types de données BINARY_FLOAT ou BINARY_DOUBLE d'Oracle.

link texte

La réponse de Bill à propos de FLOAT d’Oracle n’est corrigée que jusqu’à la dernière version (disons 11i). Dans Oracle 8i, le document indique:

  

Vous pouvez spécifier des nombres à virgule flottante avec le formulaire décrit dans   "NUMBER type de données". Oracle prend également en charge le type de données ANSI FLOAT. Vous   pouvez spécifier ce type de données en utilisant l’une des formes syntaxiques suivantes:

     

FLOAT spécifie un nombre à virgule flottante avec une précision décimale 38, ou   précision binaire 126. FLOAT (b) spécifie un nombre à virgule flottante avec   précision binaire b. La précision b peut aller de 1 à 126. Pour   convertir de précision binaire en précision décimale, multiplier b par 0,30103. À   convertir de précision décimale en précision binaire, multiplier la décimale   précision de 3.32193. Le maximum de 126 chiffres de précision binaire est   à peu près équivalente à 38 chiffres de précision décimale.

Cela ressemble à une précision quadruple (précision binaire de 126). Si je ne me trompe pas, IEEE754 ne requiert que b = 2, p = 24 pour une simple précision et p = 53 pour une double précision. Les différences entre 8i et 11i ont créé beaucoup de confusion lorsque j’étais à la recherche d’un plan de conversion entre Oracle et PostgreSQL.

Comme le PLS_INTEGER mentionné précédemment, les types BINARY_FLOAT et BINARY_DOUBLE dans Oracle 10g utilisent l'arithmétique des machines et nécessitent moins d'espace de stockage, ce qui les rend plus efficaces que le type NUMBER

  • UNIQUEMENT BINARY_FLOAT et BINARY_DOUBLE prennent en charge les valeurs NAN

- calculs pas précis

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top