94 votes

Convertir un double en BigDecimal et définir la précision BigDecimal

En Java, je veux prendre une valeur double et la convertir en une valeur de BigDecimal et imprimer sa valeur String avec une certaine précision.

import java.math.BigDecimal;
public class Main {
    public static void main(String[] args) {
        double d=-.00012;
        System.out.println(d+""); //This prints -1.2E-4

        double c=47.48000;
        BigDecimal b = new BigDecimal(c);
        System.out.println(b.toString()); 
        //This prints 47.47999999999999687361196265555918216705322265625 
    }
}

Il imprime ce truc énorme :

47.47999999999999687361196265555918216705322265625

et non

47.48

La raison pour laquelle je fais le BigDecimal la conversion est parfois la valeur double contiendra beaucoup de décimales (par ex. -.000012 ) et lorsque l'on convertit le double en String, on obtient la notation scientifique -1.2E-4 . Je veux stocker la valeur de la chaîne en notation non scientifique.

Je veux que BigDecimal ait toujours deux unités de précision comme ceci : "47.48". BigDecimal peut-il restreindre la précision lors de la conversion en chaîne de caractères ?

143voto

Piotrek De Points 3566

La raison d'un tel comportement est que la chaîne qui est imprimée est la valeur exacte - probablement pas celle que vous attendiez, mais c'est la valeur réelle stockée en mémoire - c'est juste une limitation de la représentation en virgule flottante.

Selon la javadoc, le comportement du constructeur BigDecimal(double val) peut être inattendu si vous ne tenez pas compte de cette limitation :

Les résultats de ce constructeur peuvent être quelque peu imprévisibles. Une personne pourrait supposer que l'écriture d'un nouveau BigDecimal(0.1) en Java crée un nouveau BigDecimal(0.1). BigDecimal qui est exactement égal à 0,1 (une valeur non échelonnée de 1, avec une échelle de 1). une échelle de 1), mais il est en fait égal à 0.1000000000000000055511151231257827021181583404541015625. En effet, 0,1 ne peut pas être représenté exactement comme un double (ou, d'ailleurs, comme une fraction binaire). une fraction binaire de longueur finie). Ainsi, la valeur qui est transmise au constructeur n'est pas exactement égale à 0,1, malgré les apparences.

Donc, dans votre cas, au lieu d'utiliser

double val = 77.48;
new BigDecimal(val);

utiliser

BigDecimal.valueOf(val);

La valeur qui est renvoyée par BigDecimal.valueOf est égale à celle résultant de l'invocation de Double.toString(double) .

65voto

Gilberto Torrezan Points 3530

Il imprime 47.48000 si vous utilisez une autre méthode. MathContext :

BigDecimal b = new BigDecimal(d, MathContext.DECIMAL64);

Il suffit de choisir le contexte dont vous avez besoin.

19voto

Jonathan Paulson Points 635

Vous voulez essayer String.format("%f", d) qui imprimera votre double en notation décimale. N'utilisez pas BigDecimal du tout.

En ce qui concerne la question de la précision : Vous stockez d'abord 47.48 dans le double c puis en créant une nouvelle BigDecimal de cela double . La perte de précision consiste à attribuer à c . Vous pourriez faire

BigDecimal b = new BigDecimal("47.48")

pour éviter de perdre toute précision.

8voto

urOutsourced Points 186

Pourquoi ne pas le faire ?

b = b.setScale(2, RoundingMode.HALF_UP);

6voto

Louis Wasserman Points 67557

Il imprime la valeur réelle et exacte de la double .

Double.toString() qui convertit double s à String s, fait no imprime la valeur décimale exacte de l'entrée -- si x est votre valeur double, elle imprime exactement assez de chiffres pour que x est le plus proche double à la valeur qu'il a imprimée.

Le fait est qu'il y a il n'y en a pas double comme 47,48 exactement. Les doubles enregistrent les valeurs suivantes binaire des fractions, et non des décimales, de sorte qu'il ne peut pas stocker des valeurs décimales exactes. (C'est pourquoi BigDecimal est pour !)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X