web-dev-qa-db-fra.com

Double valeur à arrondir en Java

J'ai une double valeur = 1.068879335 je veux l'arrondir avec seulement deux valeurs décimales comme 1.07.

J'ai essayé comme ça

DecimalFormat df=new DecimalFormat("0.00");
String formate = df.format(value);
double finalValue = Double.parseDouble(formate) ;

cela me donne cette exception suivante 

Java.lang.NumberFormatException: For input string: "1,07"
     at Sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.Java:1224)
     at Java.lang.Double.parseDouble(Double.Java:510)

quelqu'un peut-il me dire ce qui ne va pas avec mon code? 

enfin j'ai besoin de la valeur finale = 1.07;

34
jimmy

Notez la virgule dans votre chaîne: "1,07". DecimalFormat utilise une chaîne de séparation spécifique à l'environnement local, contrairement à Double.parseDouble(). Lorsque vous vivez dans un pays où le séparateur décimal est ",", vous ne pouvez pas analyser votre numéro.

Cependant, vous pouvez utiliser la même DecimalFormat pour la réanalyser:

DecimalFormat df=new DecimalFormat("0.00");
String formate = df.format(value); 
double finalValue = (Double)df.parse(formate) ;

Mais vous devriez vraiment faire ceci à la place:

double finalValue = Math.round( value * 100.0 ) / 100.0;

Remarque: Comme il a été souligné, vous ne devez utiliser la virgule flottante que si vous n'avez pas besoin d'un contrôle précis de la précision. (Les calculs financiers sont l'exemple principal de quand pas pour les utiliser.)

76
biziclop

La solution Live @ Sergey mais avec une division entière.

double value = 23.8764367843;
double rounded = (double) Math.round(value * 100) / 100;
System.out.println(value +" rounded is "+ rounded);

empreintes

23.8764367843 rounded is 23.88

EDIT: Comme le souligne Sergey, il ne devrait y avoir aucune différence entre multiplier double * int et double * double et diviser double/int et double/double. Je ne trouve pas d'exemple où le résultat est différent. Cependant, sur les systèmes x86/x64 et autres systèmes, il existe une instruction de code machine spécifique pour les valeurs mixtes double, int, que la machine virtuelle Java utilise, je crois.

for (int j = 0; j < 11; j++) {
    long start = System.nanoTime();
    for (double i = 1; i < 1e6; i *= 1.0000001) {
        double rounded = (double) Math.round(i * 100) / 100;
    }
    long time = System.nanoTime() - start;
    System.out.printf("double,int operations %,d%n", time);
}
for (int j = 0; j < 11; j++) {
    long start = System.nanoTime();
    for (double i = 1; i < 1e6; i *= 1.0000001) {
        double rounded = (double) Math.round(i * 100.0) / 100.0;
    }
    long time = System.nanoTime() - start;
    System.out.printf("double,double operations %,d%n", time);
}

Impressions

double,int operations 613,552,212
double,int operations 661,823,569
double,int operations 659,398,960
double,int operations 659,343,506
double,int operations 653,851,816
double,int operations 645,317,212
double,int operations 647,765,219
double,int operations 655,101,137
double,int operations 657,407,715
double,int operations 654,858,858
double,int operations 648,702,279
double,double operations 1,178,561,102
double,double operations 1,187,694,386
double,double operations 1,184,338,024
double,double operations 1,178,556,353
double,double operations 1,176,622,937
double,double operations 1,169,324,313
double,double operations 1,173,162,162
double,double operations 1,169,027,348
double,double operations 1,175,080,353
double,double operations 1,182,830,988
double,double operations 1,185,028,544
18
Peter Lawrey

Le problème est que vous utilisez un formateur de localisation qui génère un point décimal spécifique à l'environnement local, qui est "," dans votre cas. Mais Double.parseDouble () attend un double littéral non localisé. Vous pouvez résoudre votre problème en utilisant une méthode d’analyse spécifique aux paramètres régionaux ou en remplaçant les paramètres régionaux de votre programme de formatage par un élément utilisant "." comme le point décimal. Ou mieux encore, évitez les mises en forme inutiles en utilisant quelque chose comme ceci:

double rounded = (double) Math.round(value * 100.0) / 100.0;
6
Sergei Tachenov

Il y a quelque chose de fondamentalement faux dans ce que vous essayez de faire. Les valeurs à virgule flottante binaires n'ont pas n'ont de décimales. Vous ne pouvez pas arrondir significativement un à un nombre donné de décimales, car la plupart des valeurs décimales "arrondies" ne peuvent tout simplement pas être représentées sous forme de fraction binaire. C'est pourquoi on ne devrait jamais utiliser float ou double pour représenter de l'argent.

Donc, si vous voulez des décimales dans votre résultat, ce résultat doit être soit une String (que vous avez déjà avec DecimalFormat), soit une BigDecimal (qui a une méthode setScale() qui fait exactement ce que vous voulez). Sinon, le résultat ne peut pas être ce que vous voulez.

Lisez Le Guide de la virgule flottante pour plus d’informations.

4
Michael Borgwardt

Vous pouvez essayer de définir un nouveau DecimalFormat et de l’utiliser comme résultat Double pour une nouvelle variable double.

Exemple donné pour vous faire comprendre ce que je viens de dire.

double decimalnumber = 100.2397;
DecimalFormat dnf = new DecimalFormat( "#,###,###,##0.00" );
double roundednumber = new Double(dnf.format(decimalnumber)).doubleValue();
1
Markku
double TotalPrice=90.98989898898;

  DecimalFormat format_2Places = new DecimalFormat("0.00");

    TotalPrice = Double.valueOf(format_2Places.format(TotalPrice));
1
DeltaCap019

Ceci n'est pas possible de la manière demandée car il existe des nombres avec deux décimales qui ne peuvent pas être exprimés exactement à l'aide de nombres à virgule flottante IEEE (par exemple, 1/10 = 0.1 ne peut pas être exprimé sous la forme Double ou Float). Le formatage doit toujours avoir lieu à la dernière étape avant de présenter le résultat à l'utilisateur.

Je suppose que vous demandez parce que vous voulez traiter avec des valeurs monétaires. Il n’ya aucun moyen de le faire de manière fiable avec des nombres à virgule flottante, vous devriez envisager de passer à l’arithmétique à virgule fixe. Cela signifie probablement que tous les calculs doivent être effectués en "cents" au lieu de "dollars".

1
Waldheinz

Vous pouvez utiliser un format comme ici ,

  public static double getDoubleValue(String value,int digit){
    if(value==null){
        value="0";
     }
    double i=0;
     try {
         DecimalFormat digitformat = new DecimalFormat("#.##");
         digitformat.setMaximumFractionDigits(digit);
        return Double.valueOf(digitformat.format(Double.parseDouble(value)));

    } catch (NumberFormatException numberFormatExp) {
        return i;   
    }
}
0
Knowledge Serve