Utilisation de java.math.MathContext

Récemment, j’ai essayé de comprendre l’utilisation de java.math.MathContext mais j’ai échoué à comprendre correctement. Est-il utilisé pour arrondir dans java.math.BigDecimal . Si oui, pourquoi ne pas arrondir les chiffres décimaux mais même la partie mantisse.

À partir de la documentation de l’API, j’ai appris qu’elle ANSI X3.274-1996 la norme spécifiée dans ANSI X3.274-1996 et ANSI X3.274-1996/AM 1-2000 mais je ne les ai pas lues en ligne.

S’il vous plaît laissez-moi savoir si vous avez une idée à ce sujet.

@jatan

Merci pour votre réponse. Ca a du sens. Pouvez-vous s’il vous plaît m’expliquer MathContext dans le contexte de la méthode BigDecimal # round.

Il n’y a rien de spécial à propos de BigDecimal.round() rapport à toute autre méthode BigDecimal . Dans tous les cas, le MathContext spécifie le nombre de chiffres significatifs et la technique d’arrondi. Fondamentalement, il y a deux parties de chaque MathContext . Il y a une précision, et il y a aussi un RoundingMode .

La précision spécifie à nouveau le nombre de chiffres significatifs. Donc, si vous spécifiez 123 comme un nombre et demandez 2 chiffres significatifs, vous obtiendrez 120 . Cela peut être plus clair si vous pensez en termes de notation scientifique.

123 serait 1.23e2 en notation scientifique. Si vous ne conservez que 2 chiffres significatifs, vous obtenez alors 1.2e2 ou 120 . En réduisant le nombre de chiffres significatifs, nous réduisons la précision avec laquelle nous pouvons spécifier un nombre.

La partie RoundingMode spécifie comment gérer la perte de précision. Pour réutiliser l’exemple, si vous utilisez 123 comme numéro et demandez 2 chiffres significatifs, vous avez réduit votre précision. Avec un RoundingMode de HALF_UP (le mode par défaut), 123 deviendra 120 . Avec un RoundingMode de CEILING , vous obtiendrez 130 .

Par exemple:

 System.out.println(new BigDecimal("123.4", new MathContext(4,RoundingMode.HALF_UP))); System.out.println(new BigDecimal("123.4", new MathContext(2,RoundingMode.HALF_UP))); System.out.println(new BigDecimal("123.4", new MathContext(2,RoundingMode.CEILING))); System.out.println(new BigDecimal("123.4", new MathContext(1,RoundingMode.CEILING))); 

Les sorties:

 123.4 1.2E+2 1.3E+2 2E+2 

Vous pouvez voir que la précision et le mode d’arrondi affectent la sortie.

Pour arrondir juste la partie fractionnaire d’un BigDecimal, consultez la méthode BigDecimal.setScale(int newScale, int roundingMode) .

Par exemple, pour changer un nombre à trois chiffres après la virgule décimale, choisissez un chiffre à deux chiffres et arrondissez-le à:

 BigDecimal original = new BigDecimal("1.235"); BigDecimal scaled = original.setScale(2, BigDecimal.ROUND_HALF_UP); 

Le résultat de ceci est un BigDecimal avec la valeur 1.24 (en raison de la règle d’arrondi)

J’appendais ici quelques exemples. Je ne les ai pas trouvés dans les réponses précédentes, mais je les trouve utiles pour ceux qui peuvent induire en erreur des chiffres significatifs avec un nombre de décimales . Supposons, nous avons un tel contexte:

 MathContext MATH_CTX = new MathContext(3, RoundingMode.HALF_UP); 

Pour ce code:

 BigDecimal d1 = new BigDecimal(1234.4, MATH_CTX); System.out.println(d1); 

il est parfaitement clair que votre résultat est 1.23E+3 comme dit les gars ci-dessus. Les premiers chiffres significatifs sont 123 …

Mais que dans ce cas:

 BigDecimal d2 = new BigDecimal(0.000000454770054, MATH_CTX); System.out.println(d2); 

votre numéro ne sera pas arrondi à 3 places après la virgule – pour quelqu’un, cela peut ne pas être intuitif et mérite d’être souligné. Au lieu de cela, il sera arrondi aux 3 premiers chiffres significatifs , qui dans ce cas sont “4 5 4”. Donc, le code ci-dessus donne 4.55E-7 et non pas 0.000 comme on pouvait s’y attendre.

Exemples similaires:

 BigDecimal d3 = new BigDecimal(0.001000045477, MATH_CTX); System.out.println(d3); // 0.00100 BigDecimal d4 = new BigDecimal(0.200000477, MATH_CTX); System.out.println(d4); // 0.200 BigDecimal d5 = new BigDecimal(0.000000004, MATH_CTX); System.out.println(d5); //4.00E-9 

J’espère que cette évidence, mais exemple pertinent serait utile …

Si je vous comprends bien, il semblerait que MathContext contrôle le nombre de chiffres à conserver après le point décimal. Ce n’est pas pour ça. Il spécifie le nombre de chiffres à conserver, total . Donc, si vous spécifiez que vous voulez 3 chiffres significatifs, c’est tout ce que vous allez obtenir.

Par exemple, ceci:

 System.out.println(new BigDecimal("1234567890.123456789", new MathContext(20))); System.out.println(new BigDecimal("1234567890.123456789", new MathContext(10))); System.out.println(new BigDecimal("1234567890.123456789", new MathContext(5))); 

va sortir:

 1234567890.123456789 1234567890 1.2346E+9 

Ce n’est pas pour s’amuser. En fait, j’ai trouvé un exemple en ligne, qui indiquait l’utilisation de MathContext pour arrondir les montants / nombres stockés dans BigDecimal.

Par exemple,

Si MathContext est configuré pour avoir une precision = 2 et un rounding mode = ROUND_HALF_EVEN

BigDecimal Number = 0.5294 , est arrondi à 0.53

Alors j’ai pensé que c’était une technique plus récente et je l’ai utilisée pour arrondir les objectives. Cependant, cela a tourné au cauchemar car il a commencé à arrondir même la partie de numéro de mentissa.

Par exemple,

Number = 1.5294 est arrondi à 1.5

Number = 10.5294 est arrondi à 10

Number = 101.5294 est arrondi à 100

…. etc

Donc, ce n’est pas le comportement que j’attendais pour l’arrondi (comme précision = 2).

Il semble y avoir une certaine logique parce que de patter je peux dire qu’il prend les deux premiers chiffres (comme la précision est 2) du nombre et ajoute ensuite les 0 jusqu’au no. des chiffres deviennent identiques au montant non arrondi (consultez l’exemple de 101.5294 …)