Question

Récemment, j'ai essayé de comprendre l'utilisation de java.math.MathContext mais je n'ai pas réussi à bien comprendre.Est-il utilisé pour arrondir java.math.BigDecimal.Si oui, pourquoi n'arrondit-il pas les chiffres décimaux mais même la partie mantisse.

Grâce à la documentation de l'API, j'ai appris qu'elle suit la norme spécifiée dans ANSI X3.274-1996 et ANSI X3.274-1996/AM 1-2000 spécifications mais je ne les ai pas fait lire en ligne.

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

Était-ce utile?

La solution

@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 BigDecimal.round() contre. tout autre BigDecimal méthode.Dans tous les cas, le MathContext précise le nombre de chiffres significatifs et la technique d'arrondi.Fondamentalement, il y a deux parties dans chaque MathContext.Il y a une précision, et il y a aussi un RoundingMode.

La précision précise à nouveau le nombre de chiffres significatifs.Donc si tu précise 123 sous forme de nombre, et demandez 2 chiffres significatifs, vous obtiendrez 120.Cela pourrait être plus clair si vous raisonnez en termes de notation scientifique.

123 serait 1.23e2 en notation scientifique.Si vous ne gardez que 2 chiffres significatifs, vous obtenez 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.

Le RoundingMode La partie précise comment nous devons gérer la perte de précision.Pour réutiliser l'exemple, si vous utilisez 123 comme nombre, et demandez 2 chiffres significatifs, vous avez réduit votre précision.Avec un RoundingMode de HALF_UP (le mode par défaut), 123 va devenir 120.Avec un RoundingMode de CEILING, tu auras 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 le résultat.

Autres conseils

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

Par exemple.pour changer un nombre à trois chiffres après la virgule en un nombre à deux chiffres, et arrondir :

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

Le résultat est un BigDecimal avec la valeur 1,24 (en raison de la règle d'arrondi)

J'ajouterais 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 pourraient induire en erreur chiffres significatifs avec nombre de décimales.Supposons que nous ayons le contexte suivant :

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 les gars l'ont dit plus haut.Les premiers chiffres significatifs sont 123...

Mais que se passe-t-il dans ce cas :

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

ton numéro ne sera pas arrondi à 3 chiffres 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 au 3 premiers chiffres significatifs, qui dans ce cas sont "4 5 4".Donc, le code ci-dessus donne 4.55E-7 et pas dans 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 cet exemple évident, mais pertinent, serait utile...

Si je vous comprends bien, il semble que vous vous attendiez à ce que MathContext contrôle le nombre de chiffres à conserver après la virgule.Ce n'est pas pour ça.Il précise combien de chiffres conserver, total.Donc, si vous précisez que vous voulez 3 chiffres significatifs, c'est tout ce que vous obtiendrez.

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)));

affichera :

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 precision = 2 et rounding mode = ROUND_HALF_EVEN

BigDecimal Number = 0.5294, est arrondi à 0.53

J'ai donc pensé qu'il s'agissait d'une technique plus récente et je l'ai utilisée à des fins d'arrondi.Cependant, cela s'est transformé en cauchemar car il a commencé à arrondir même une partie mentissa du nombre.

Par exemple,

Number = 1.5294 est arrondi à 1.5

Number = 10.5294 est arrondi à 10

Number = 101.5294 est arrondi à 100

....et ainsi de suite

Ce n'est donc pas le comportement auquel je m'attendais pour l'arrondi (car précision = 2).

Cela semble avoir une certaine logique car, d'après le modèle, je peux dire qu'il prend les deux premiers chiffres (la précision étant de 2) du nombre, puis ajoute des 0 jusqu'au non.de chiffres deviennent identiques au montant non arrondi (consultez l'exemple de 101,5294 ...)

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