2017-03-06 1 views
0

J'essaye de comprendre l'échelle pour un BigDecimal mais il agit bizarrement et je ne peux pas comprendre pourquoi. Voici quelques exemples:Échelle BigDecimal pour les grands nombres

Double d = new Double(1000000d); 
int scale = new BigDecimal(d.toString()).scale(); 

L'échelle de cet exemple sera 1, ce qui est correct pour moi. Le résultat de d.toString() est "1000000.0".

Double d = new Double(10000000d); 
int scale = new BigDecimal(d.toString)).scale(); 

L'échelle de cet exemple sera -6. Quelqu'un peut-il expliquer pourquoi? Le résultat de d.toString() est "1.0E7".

Je pensais que le nombre de chiffres a causé cela, mais si je vais:

Double d = new Double(11111111d); 
int scale = new BigDecimal(d.toString()).scale(); 

une échelle de escomptés -8 mais tout à coup, il est 0. Le résultat de d.toString() est « 1.1111111E7 ».

Ces différentes échelles pour me faire aucun sens après avoir lu la Javadoc d'échelle():

Renvoie l'échelle de ce BigDecimal. Si zéro ou positif, l'échelle est le nombre de chiffres à la droite de la virgule décimale. Si négatif, la valeur non scalée du nombre est multipliée par dix à la puissance de la négation de l'échelle. Par exemple, une échelle de -3 signifie que la valeur non mise à l'échelle est multipliée par 1000.

J'apprécierais beaucoup l'explication du comportement de BigDecimal lorsque les nombres sont grands.

Merci d'avance!

+1

Vérifiez la valeur de 'd.toString()' avant de le passer à 'new BigDecimal'. Il pourrait ne pas avoir la valeur que vous pensez avoir. – marstran

+0

Ajout des résultats de d.toString() pour les exemples et cela ne m'aide pas beaucoup. –

Répondre

3

L'échelle que vous avez est le nombre de décimales avec une certaine importance:

  • 1000000d -> 1.000.000,0 -> 0: les chiffres à la droite du point ont aucune signification, le résultat est 0;
  • 10000000d -> 1.0E7 -> -6: les chiffres à droite du point ont une signification, comme si vous dénormalisiez la puissance par dix vous obtenez les 6 zéros;
  • 11111111d -> 1.1111111E7 -> 0: tous les nombres à la droite du point ont une signification, dénormalisant la puissance par dix vous obtenez plus d'informations, de sorte que vous ne pouvez pas normaliser le nombre si vous voulez garder cette information. De cette façon (le nombre dénormalisé), vous avez 0 numéros à droite du point.

EDIT

Comme commenté, la première ligne est mauvaise, il doit être 1000000d -> 1000000.0 -> 1. La raison en est que les nombres avec exponentielle ont un comportement différent (en obtenant l'échelle) que les nombres formatés.

La valeur de 1 est due que BigDecimal compte les chiffres dans la partie droite du point (qui dans ce cas est l'un, un seul 0), soustraire les nombres à déposer (dans ce cas il existe, le seul 0) et ajoutez la précision mathématique (par défaut est une) -> résultat = 1.

+0

Compliqué mais je pense que je l'obtiens :) Merci! –

+0

'1000000d -> 1000000.0 -> 0' devrait être' 1' – vossad01

+0

Non, devrait être '0' car 0 dans le côté droit du point n'a aucune signification –

1

Vous voyez le comportement de votre rapport parce que vous appelez toString() sur la décimale fournie, qui dans certains de vos exemples représente en notation exponentielle, qui est ensuite conservé par BigDecimal lorsqu'il choisit l'échelle.

Si vous fournissez le double directement au constructeur BigDecimal vous obtenez toujours 0.

new Double(1000000d).toString() //1.0E7 

Double d = new Double(1000000d); 
int scale = new BigDecimal(d).scale(); //0 

Double d = new Double(10000000d); 
int scale = new BigDecimal(d).scale(); //0 

Double d = new Double(11111111d); 
int scale = new BigDecimal(d).scale(); //0 

Mise à jour:

scale est est pas un attribut utile en soi. Il doit être considéré conjointement avec unscaledValue. Le nombre représenté est unscaledValue × 10^-scale.

C'est,

BigDecimal d = new BigDecimal(1000000d) 
BigDecimal e = d.setScale(2) 

int dScale = d.scale() //0 
int dUnscaled = d.unscaledValue() //1000000 

int eScale = e.scale() //2 
int eUnscaled = e.unscaledValue() //100000000 

Les deux d et e sont une représentation de 1000000. Cependant, e préserve il y a 2 zéros de fin (zéros après la virgule décimale).

d.toString() //1000000 
e.toString() //1000000.00 
+0

Merci! J'utiliserai les doubles lorsque j'initialiser mes BigDecimals. –