Comment imprimer une valeur double sans notation scientifique en utilisant Java?

222

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 l'imprimer comme ceci: 12345678

Quelle est la meilleure façon d'empêcher cela?

Méprisable
la source

Réponses:

116

Vous pouvez utiliser printf()avec %f:

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

Cela s'imprimera dexp: 12345678.000000. Si vous ne voulez pas la partie fractionnaire, utilisez

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

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

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

NPE
la source
1
mais il a montré dexp: 12345681.000000quelle est la mauvaise valeur. Et en fait après cela, je veux l'afficher sur ma page Web où il s'affiche comme ceci. 1.2345678E7Y a-t-il de toute façon à travers lequel je peux le stocker dans n'importe quel double comme 12345678et de toute autre manière?
Despicable
1
@despicable: Vous avez peut-être consulté l'ancienne version incomplète de la réponse. Essayez de recharger la page. Il devrait y avoir un paragraphe sur %.0f.
NPE
@despicable vous pouvez stocker dexp en tant qu'int afin que vous puissiez facilement l'utiliser dans les deux sens
Justin
10
IL RONDE LE NOMBRE
Confondre
6
%.0farrondit le nombre. Existe-t-il un moyen de simplement supprimer les zéros de fin?
NurShomik
239

Java empêche la notation E dans un double:

Cinq façons différentes de convertir un double en 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 ont 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 valeur double, cette vidéo explique: computerphile pourquoi 0.1+ est-il 0.2égal 0.30000000000001?

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

Eric Leschinski
la source
Merci beaucoup pour la réponse et surtout l'astuce .. Cette vidéo a résolu ma confusion.
AnujDeo
97

En bref:

Si vous souhaitez vous débarrasser des zéros de fin 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 les autres réponses ne me convenaient pas:

  • Double.toString()ou System.out.printlnou FloatingDecimal.toJavaFormatStringutilise des notations scientifiques si le 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 la coder en dur, mais elle entraîne des zéros supplémentaires 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 %.0fvous supprimez toute précision décimale, ce qui est bien 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 dépendez localement. Dans les paramètres régionaux 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 des paramètres régionaux ANGLAIS garantit que vous obtenez un point pour le séparateur décimal, où que votre programme s'exécute.

Pourquoi utiliser 340 alors setMaximumFractionDigits?

Deux raisons:

  • setMaximumFractionDigitsaccepte un entier, mais son implémentation a un maximum de chiffres autorisés DecimalFormat.DOUBLE_FRACTION_DIGITSdont 340
  • Double.MIN_VALUE = 4.9E-324 Ainsi, avec 340 chiffres, vous êtes sûr de ne pas arrondir votre double et de perdre en précision.
JBE
la source
Quelle est votre opinion de new BigDecimal(myvalue).toPlainString()la description à docs.oracle.com/javase/7/docs/api/java/math/… ), il n'est pas immédiatement évident comment il se comporte lorsqu'il est donné différents types de nombres, mais il élimine la notation scientifique .
Derek Mahar
4
new BigDecimal(0.00000021d).toPlainString()sortie 0.0000002100000000000000010850153241148685623329583904705941677093505859375qui n'est pas ce que vous attendez ...
JBE
une idée de comment utiliser votre réponse en scala? c'est probablement une question d'importations appropriées mais je suis nouveau ici.
jangorecki
BigDecimal.valueOf(0.00000021d).toPlainString()fonctionne aussi (il utilise le constructeur String de BigDecimal c'est pourquoi)
marco
27

Vous pouvez l'essayer avec DecimalFormat. Avec cette classe, vous êtes très flexible dans l'analyse de vos numéros.
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
Obl Tobl
la source
16

J'ai une autre solution impliquant toPlainString () de BigDecimal, mais cette fois en utilisant le constructeur de chaîne, qui est 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 préféré pour convertir un flottant ou un double en BigDecimal, car il ne souffre pas de l'imprévisibilité du constructeur BigDecimal (double).

Il ressemble à ceci sous sa forme la plus courte:

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

Avant Java 8, cela se traduit par «0,0» pour tous les doubles à valeur nulle, vous devez donc ajouter:

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

Les valeurs NaN et infinies doivent être vérifiées 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.

Manuel
la source
2
J'ai lu d'innombrables schémas pour convertir une valeur double en une chaîne et c'est le meilleur: court, simple, configurable.
Paul
Excellente solution, m'a vraiment aidé à convertir les valeurs doubles en chaîne et à éviter la notation scientifique. Merci!
pleft
Pourquoi d.doubleValue() == 0au lieu de d == 0?
Alexei Fando
Parce que cela évite le déballage automatique, ce que j'aime mieux dans cette situation, mais les vues peuvent bien sûr différer à ce sujet. Si vous êtes sur java 8 (9 sera probablement le même), vous pouvez laisser de côté ces 2 lignes.
Manuel
Juste essayé avec java 9, ces 2 lignes peuvent également être omises sur 9.
Manuel
8

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 la tronquera.

NateS
la source
4

J'ai dû convertir des valeurs doubles en devises et j'ai constaté que la plupart des solutions étaient correctes, mais pas pour moi.

Le DecimalFormatfut finalement le chemin pour moi, alors voici ce que je l' 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 voir, si le nombre est naturel, je reçois - disons - 20000000 au lieu de 2E7 (etc.) - sans point décimal.

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

JamesC
la source
4

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

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 text view using setText() function */
        salesTextView.setText( valueWithoutEpsilon.toPlainString() )
    }
Ramakrishna Joshi
la source
3

Le code suivant détecte si le nombre 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);
}
Memin
la source
2

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

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

J'utilise Eclipse et cela n'a pas fonctionné.

J'espère que cela vous a été utile. J'apprécierais toute rétroaction!

Brian Castro
la source
1

J'ai eu ce 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 comme "x + 20/50"

J'ai regardé des centaines d'articles ... Au final, je suis allé avec ça à cause de la vitesse. Et parce que la fonction Eval allait finalement la reconvertir dans son propre format numérique et math.Eval () ne supportait pas le E-07 final que les autres méthodes renvoyaient, et tout ce qui dépassait 5 dp était de toute façon trop détaillé pour mon application .

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

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

s display as:  0.00021
hamish
la source
1

Cela peut être une tangente .... mais si vous avez besoin de mettre une valeur numérique sous forme d'entier (qui est trop grand pour être un entier) dans un sérialiseur (JSON, etc.) alors vous voudrez probablement "BigInterger"

Exemple: la valeur est une chaîne - 7515904334

Nous devons le représenter sous forme numérique dans un message Json: {"contact_phone": "800220-3333", "servicer_id": 7515904334, "servicer_name": "SOME CORPORATION"}

Nous ne pouvons pas l'imprimer ou nous obtiendrons ceci: {"contact_phone": "800220-3333", "servicer_id": "7515904334", "servicer_name": "SOME CORPORATION"}

L'ajout de la valeur au nœud comme ceci produit le résultat souhaité: BigInteger.valueOf (Long.parseLong (value, 10))

Je ne suis pas sûr que ce soit vraiment sur le sujet, mais comme cette question a été mon principal succès lorsque j'ai cherché ma solution, j'ai pensé partager ici pour le bénéfice des autres, mentez-moi, qui cherche mal. :RÉ

Keith Fosberg
la source
-1

Pour les valeurs entières représentées par un 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);
}
rmuller
la source
-1

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

Nguyễn Thắng
la source