Question

j'ai un XSD cela m'oblige à utiliser un BigDecimal pour un lat/lon.J'ai actuellement le lat/lon en double et je les convertis en BigDecimal, mais je ne dois utiliser qu'environ 12 lieux de précision.Je n'ai pas réussi à comprendre comment régler cela.Est-ce que quelqu'un peut m'aider avec ça?

Était-ce utile?

La solution

Le titre de la question porte sur la précision. GrandDécimal fait la distinction entre échelle et précision.L'échelle est le nombre de décimales.Vous pouvez considérer la précision comme le nombre de chiffres significatifs, également appelés chiffres significatifs.

Quelques exemples dans Clojure.

(.scale     0.00123M) ; 5
(.precision 0.00123M) ; 3

(Dans Clojure, Le M désigne un littéral BigDecimal.Vous pouvez traduire le Clojure en Java si vous le souhaitez, mais je le trouve plus compact que Java !)

Vous pouvez facilement augmenter l'échelle :

(.setScale 0.00123M 7) ; 0.0012300M

Mais tu ne peux pas diminuer l'échelle de la même manière :

(.setScale 0.00123M 3) ; ArithmeticException Rounding necessary

Vous devrez également passer un mode d'arrondi :

(.setScale 0.00123M 3 BigDecimal/ROUND_HALF_EVEN) ;
; Note: BigDecimal would prefer that you use the MathContext rounding
; constants, but I don't have them at my fingertips right now.

Il est donc facile de changer d’échelle.Mais qu’en est-il de la précision ?Ce n’est pas aussi simple qu’on pourrait l’espérer !

C'est facile de diminuer la précision :

(.round 3.14159M (java.math.MathContext. 3)) ; 3.14M

Mais il n'est pas évident de savoir comment augmenter la précision :

(.round 3.14159M (java.math.MathContext. 7)) ; 3.14159M (unexpected)

Pour les sceptiques, c'est pas juste une question de zéros à droite qui ne sont pas affichés :

(.precision (.round 3.14159M (java.math.MathContext. 7))) ; 6 
; (same as above, still unexpected)

FWIW, Clojure fait attention aux zéros à droite et volonté montre leur:

4.0000M ; 4.0000M
(.precision 4.0000M) ; 5

Retour sur la bonne voie...Vous pouvez essayer d'utiliser un GrandDécimal constructeur, mais il ne définit pas la précision au-dessus du nombre de chiffres que vous spécifiez :

(BigDecimal. "3" (java.math.MathContext. 5)) ; 3M
(BigDecimal. "3.1" (java.math.MathContext. 5)) ; 3.1M

Il n’existe donc pas de moyen rapide de modifier la précision.J'ai passé du temps à lutter contre cela en rédigeant cette question et avec un projet sur lequel je travaille.Je considère cela, au mieux, comme une API CRAZYTOWN, et au pire comme un bug.Personnes.Sérieusement?

Donc, d'après ce que je peux dire, si vous souhaitez modifier la précision, vous devrez suivre ces étapes :

  1. Recherchez la précision actuelle.
  2. Recherchez l'échelle actuelle.
  3. Calculez le changement d’échelle.
  4. Définir la nouvelle échelle

Ces étapes, en tant que code Clojure :

(def x 0.000691M) ; the input number
(def p' 1) ; desired precision
(def s' (+ (.scale x) p' (- (.precision x)))) ; desired new scale
(.setScale x s' BigDecimal/ROUND_HALF_EVEN)
; 0.0007M

Je sais, cela fait beaucoup d'étapes juste pour changer la précision !

Pourquoi BigDecimal ne le fournit-il pas déjà ?Ai-je oublié quelque chose ?

Autres conseils

Vous pouvez utiliser setscale () par exemple

double d = ...
BigDecimal db = new BigDecimal(d).setScale(12, BigDecimal.ROUND_HALF_UP);

 BigDecimal decPrec = (BigDecimal)yo.get("Avg");
 decPrec = decPrec.setScale(5, RoundingMode.CEILING);
 String value= String.valueOf(decPrec);

De cette façon, vous pouvez définir la précision spécifique d'un BigDecimal.

La valeur de decPrec était 1.5726903423607562595809913132345426qui est arrondi à 1.57267.

Essayez ce code ...

    Integer perc = 5;
    BigDecimal spread = BigDecimal.ZERO; 
    BigDecimal perc = spread.setScale(perc,BigDecimal.ROUND_HALF_UP);
    System.out.println(perc);

résultat: 0.00000

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