web-dev-qa-db-fra.com

Comment imprimer une valeur double sans notation scientifique avec Java?

Je veux imprimer une double valeur en Java sans forme exponentielle.

double dexp = 12345678;
System.out.println("dexp: "+dexp);

Il montre cette notation E: 1.2345678E7.

Je veux que ça s'imprime comme ça: 12345678

Quel est le meilleur moyen d'éviter cela?

181
Despicable

Vous pouvez utiliser printf() avec %f:

double dexp = 12345678;
System.out.printf("dexp: %f\n", dexp);

Ceci imprimera dexp: 12345678.000000. Si vous ne voulez pas la partie décimale, utilisez

System.out.printf("dexp: %.0f\n", dexp);

Ceci utilise le langage de spécification de format expliqué dans documentation .

Le format par défaut toString() utilisé dans votre code d'origine est précisé ici .

95
NPE

Java empêche la notation E dans un double:

Cinq façons différentes de convertir un double en un nombre normal:

import Java.math.BigDecimal;
import Java.text.DecimalFormat;

public class Runner {
    public static void main(String[] args) {
        double myvalue = 0.00000021d;

        //Option 1 Print bare double.
        System.out.println(myvalue);

        //Option2, use decimalFormat.
        DecimalFormat df = new DecimalFormat("#");
        df.setMaximumFractionDigits(8);
        System.out.println(df.format(myvalue));

        //Option 3, use printf.
        System.out.printf("%.9f", myvalue);
        System.out.println();

        //Option 4, convert toBigDecimal and ask for toPlainString().
        System.out.print(new BigDecimal(myvalue).toPlainString());
        System.out.println();

        //Option 5, String.format 
        System.out.println(String.format("%.12f", myvalue));
    }
}

Ce programme imprime:

2.1E-7
.00000021
0.000000210
0.000000210000000000000001085015324114868562332958390470594167709350585
0.000000210000

Qui sont tous la même valeur.

Protip: Si vous ne savez pas pourquoi ces chiffres aléatoires apparaissent au-delà d'un certain seuil dans la double valeur, cette vidéo explique: computerphile pourquoi 0.1 + 0.2 est-il égal à 0.30000000000001?

http://youtube.com/watch?v=PZRI1IfStY0

212
Eric Leschinski

En bref:

Si vous souhaitez vous débarrasser des zéros et des problèmes de paramètres régionaux, vous devez utiliser:

double myValue = 0.00000021d;

DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(340); // 340 = DecimalFormat.DOUBLE_FRACTION_DIGITS

System.out.println(df.format(myValue)); // Output: 0.00000021

Explication:

Pourquoi d'autres réponses ne me convenaient pas:

  • Double.toString() ou System.out.println ou FloatingDecimal.toJavaFormatString utilise des notations scientifiques si double est inférieur à 10 ^ -3 ou supérieur ou égal à 10 ^ 7
  • En utilisant %f, la précision décimale par défaut est 6, sinon vous pouvez le coder en dur, mais des zéros supplémentaires sont ajoutés si vous avez moins de décimales. Exemple:

    double myValue = 0.00000021d;
    String.format("%.12f", myvalue); // Output: 0.000000210000
    
  • En utilisant setMaximumFractionDigits(0); ou %.0f, vous supprimez toute précision décimale, ce qui est correct pour les entiers/longs, mais pas pour le double:

    double myValue = 0.00000021d;
    System.out.println(String.format("%.0f", myvalue)); // Output: 0
    DecimalFormat df = new DecimalFormat("0");
    System.out.println(df.format(myValue)); // Output: 0
    
  • En utilisant DecimalFormat, vous êtes dépendant localement. En français, le séparateur décimal est une virgule, pas un point:

    double myValue = 0.00000021d;
    DecimalFormat df = new DecimalFormat("0");
    df.setMaximumFractionDigits(340);
    System.out.println(df.format(myvalue)); // Output: 0,00000021
    

    L'utilisation de la langue anglaise garantit que vous obtenez un point pour le séparateur décimal, quel que soit le lieu d'exécution du programme.

Pourquoi utiliser 340 alors pour setMaximumFractionDigits?

Deux raisons:

  • setMaximumFractionDigits accepte un entier, mais son implémentation a un nombre maximum autorisé de DecimalFormat.DOUBLE_FRACTION_DIGITS, ce qui équivaut à 340
  • Double.MIN_VALUE = 4.9E-324 donc avec 340 chiffres, vous êtes sûr de ne pas arrondir votre double et de perdre de la précision.
77
JBE

Vous pouvez l'essayer avec DecimalFormat. Avec cette classe, vous êtes très flexible dans l'analyse de vos nombres.
Vous pouvez définir exactement le motif que vous souhaitez utiliser.
Dans votre cas par exemple:

double test = 12345678;
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(0);
System.out.println(df.format(test)); //12345678
25
Obl Tobl

J'ai une autre solution impliquant toPlainString () de BigDecimal, mais cette fois-ci en utilisant le constructeur String, recommandé dans le javadoc:

ce constructeur est compatible avec les valeurs renvoyées par Float.toString et Double.toString. C’est généralement le moyen privilégié de convertir un float ou un double en BigDecimal, car il ne souffre pas de l’imprévisibilité du constructeur BigDecimal (double).

Cela ressemble à ceci dans sa forme la plus courte:

return new BigDecimal(myDouble.toString()).stripTrailingZeros().toPlainString();

Avant Java 8, cela donne "0.0" pour tous les doubles à valeur zéro, vous devez donc ajouter:

if (myDouble.doubleValue() == 0)
    return "0";

NaN et les valeurs infinies doivent être vérifiés en plus.

Le résultat final de toutes ces considérations:

public static String doubleToString(Double d) {
    if (d == null)
        return null;
    if (d.isNaN() || d.isInfinite())
        return d.toString();

    // Pre Java 8, a value of 0 would yield "0.0" below
    if (d.doubleValue() == 0)
        return "0";
    return new BigDecimal(d.toString()).stripTrailingZeros().toPlainString();
}

Cela peut également être copié/collé pour fonctionner correctement avec Float.

14
Manuel

Cela fonctionnera tant que votre numéro est un nombre entier:

double dnexp = 12345678;
System.out.println("dexp: " + (long)dexp);

Si la variable double a une précision après le point décimal, elle sera tronquée.

8
NateS

J'avais besoin de convertir un double en valeurs monétaires et j'ai constaté que la plupart des solutions étaient acceptables, mais pas pour moi.

La DecimalFormat était finalement le chemin pour moi, alors voici ce que j'ai fait:

   public String foo(double value) //Got here 6.743240136E7 or something..
    {
        DecimalFormat formatter;

        if(value - (int)value > 0.0)
            formatter = new DecimalFormat("0.00"); // Here you can also deal with rounding if you wish..
        else
            formatter = new DecimalFormat("0");

        return formatter.format(value);
    }

Comme vous pouvez le constater, si le nombre est naturel, je reçois - disons - 20000000 au lieu de 2E7 (etc.) - sans décimale.

Et si c'est décimal, je n'ai que deux chiffres décimaux.

4
JamesC

Le compilateur Java/Kotlin convertit toute valeur supérieure à 9999999 (supérieure ou égale à 10 millions) en notation scientifique, c.-à-d. Notation EPSON. 

Ex: 12345678 est converti en 1.2345678E7

Utilisez ce code pour éviter la conversion automatique en notation scientifique:

fun setTotalSalesValue(String total) {
        var valueWithoutEpsilon = total.toBigDecimal()
        /* Set the converted value to your Android view using setText() function */
        totalSalesValue.setText() = valueWithoutEpsilon.toPlainString()
    }
3
Ramakrishna Joshi

Le code suivant détecte si le numéro fourni est présenté en notation scientifique. Si tel est le cas, il est représenté dans une présentation normale avec un maximum de 25 chiffres.

 static String convertFromScientificNotation(double number) {
    // Check if in scientific notation
    if (String.valueOf(number).toLowerCase().contains("e")) {
        System.out.println("The scientific notation number'"
                + number
                + "' detected, it will be converted to normal representation with 25 maximum fraction digits.");
        NumberFormat formatter = new DecimalFormat();
        formatter.setMaximumFractionDigits(25);
        return formatter.format(number);
    } else
        return String.valueOf(number);
}
3
Memin

J'ai eu le même problème dans mon code de production lorsque je l'utilisais comme entrée de chaîne dans une fonction math.Eval () qui prend une chaîne telle que "x + 20/50"

J'ai regardé des centaines d'articles ... Finalement, j'y suis allé à cause de la vitesse. Et parce que la fonction Eval allait finalement la reconvertir en son propre format numérique et que math.Eval () ne prend pas en charge le dernier E-07 renvoyé par d'autres méthodes, et tout dépassement de 5 dp était trop détaillé pour mon application .

Ceci est maintenant utilisé dans le code de production pour une application qui compte plus de 1 000 utilisateurs ...

double value = 0.0002111d;
String s = Double.toString(((int)(value * 100000.0d))/100000.0d); // Round to 5 dp

s display as:  0.00021
1
hamish

Pour les valeurs entières représentées par une double, vous pouvez utiliser ce code, qui est beaucoup plus rapide que les autres solutions.

public static String doubleToString(final double d) {
    // check for integer, also see https://stackoverflow.com/a/9898613/868941 and
    // https://github.com/google/guava/blob/master/guava/src/com/google/common/math/DoubleMath.Java
    if (isMathematicalInteger(d)) {
        return Long.toString((long)d);
    } else {
        // or use any of the solutions provided by others
        return Double.toString(d);
    }
}

// Java 8+
public static boolean isMathematicalInteger(final double d) {
    return StrictMath.rint(d) == d && Double.isFinite(d);
}
0
rmuller

Je pense que tout le monde avait la bonne idée, mais toutes les réponses n'étaient pas simples. Je peux voir que c'est un morceau de code très utile. Voici un extrait de ce qui fonctionnera:

System.out.println(String.format("%.8f", EnterYourDoubleVariableHere));

le ".8" est l'endroit où vous définissez le nombre de décimales que vous souhaitez afficher.

J'utilise Eclipse et cela n'a posé aucun problème.

J'espère que c'était utile. J'apprécierais vos commentaires!

0
Brian Castro

Ma solution: String str = String.format ("% .0f", votreDouble);

0
Nguyễn Thắng