2017-04-21 2 views
2

BINARY_DOUBLE dans Oracle et Double dans Java utilisent la norme IEEE 754.Différence entre la valeur double dans Oracle et Java (IEEE 754)

Mais il y a la différence dans leur précision.

Pour valeur exemple:

456.67d

Oracle:

declare 
    a BINARY_DOUBLE := 456.67d; 
begin 
    SYS.DBMS_OUTPUT.PUT_Line(TO_CHAR(a,'9.99999999999999999999EEEE')); 
end; 

Résultat: 4.56670000000000020000E + 02

Java:

Double d = 456.67d; 
DecimalFormat formatter = new DecimalFormat("0.000000000000000000000E000"); 
System.out.println(formatter.format(d)); 

Résultat: 4.566700000000000000000E002

La valeur en Java est pas aussi précis que dans Oracle.

convertisseurs en ligne a déclaré que la représentation la plus précise pour 456.67d est:

4.56670000000000015916157281026E2

Alors, pourquoi la précision Java est pas la même chose comme dans Oracle? Et comment puis-je obtenir en Java une valeur plus précise?

Répondre

3

Utilisation BigDecimal:

Double d = 456.67d; 
BigDecimal bd = new BigDecimal(d); 
bd.setScale(50); 
System.out.println(bd); 
DecimalFormat formatter = new DecimalFormat("0.000000000000000000000E000"); 
System.out.println(formatter.format(bd)); 

Sortie:

456.67000000000001591615728102624416351318359375 
4.566700000000000159162E002 
1

Les deux sont exacts. Ils utilisent simplement une stratégie différente pour l'impression.

Voici les valeurs exactes imprimées via Smalltalk Squeak (mais la langue n'a pas d'importance, c'est même représentation et même arithmétique):

d := 456.67. 
{ 
    d predecessor asFraction printShowingMaxDecimalPlaces: 50. 
    d asFraction printShowingMaxDecimalPlaces: 50. 
    d successor asFraction printShowingMaxDecimalPlaces: 50}. 

->

#(
    '456.6699999999999590727384202182292938232421875' 
    '456.67000000000001591615728102624416351318359375' 
    '456.670000000000072759576141834259033203125' 
)  

Ainsi, toute représentation décimale entre (d predecessor asFraction + d asFraction)/2 printShowingMaxDecimalPlaces: 50. et (d successor asFraction + d asFraction)/2 printShowingMaxDecimalPlaces: 50. va être arrondi à la même valeur en virgule flottante (bornes exclues, parce que l'égalité exacte est arrondie au plus proche pair, et ce flottant a un significand impair ...)

Ainsi, les limites sont les suivantes:

#(
    '456.669999999999987494447850622236728668212890625' 
    '456.670000000000044337866711430251598358154296875' 
) 

Oracle il suffit d'utiliser 17 chiffres et ne prend pas la peine avec des chiffres plus que 17 est connu pour être assez pour distinguer les deux valeurs à virgule flottante à double précision.

Java est un peu plus intelligent: il utilise juste assez de chiffres pour distinguer des valeurs flottantes représentables suivantes. Donc, mettre 0, 1, 2, 3 ou 4 à la position 17, ou même 4.5666999999999999e2 n'a pas d'importance, c'est toujours la même valeur en virgule flottante.