124 votes

Conversion sûre de String en BigDecimal

J'essaie de lire des valeurs BigDecimal à partir d'une chaîne de caractères. Disons que j'ai cette chaîne : "1,000,000,000.999999999999999" et je veux en extraire une valeur BigDecimal. Quelle est la façon de le faire ?

Tout d'abord, je n'aime pas les solutions utilisant les remplacements de chaînes de caractères (remplacement des virgules, etc.). Je pense qu'il devrait y avoir un formateur qui fasse ce travail pour moi.

J'ai trouvé une classe DecimalFormatter, mais comme elle fonctionne avec des doubles, on perd une grande partie de la précision.

Alors, comment puis-je le faire ?

0 votes

Parce qu'avec un format personnalisé, il est difficile de le convertir en un format compatible avec BigDecimal.

2 votes

"Parce que, étant donné un certain format personnalisé, c'est une douleur..." Je ne sais pas, ça sépare en quelque sorte les domaines de problèmes. Tout d'abord, vous nettoyez les éléments lisibles par l'homme de la chaîne de caractères, puis vous passez le relais à quelque chose qui sait comment transformer correctement et efficacement le résultat en un fichier de type BigDecimal .

91voto

Jeroen Rosenberg Points 1510

Vérifiez setParseBigDecimal dans DecimalFormat. Avec ce setter, parse retournera un BigDecimal pour vous.

1 votes

Le constructeur de la classe BigDecimal ne prend pas en charge les formats personnalisés. L'exemple que j'ai donné dans la question utilise le format personnalisé (virgules). Vous ne pouvez pas l'analyser dans BigDecimal en utilisant son constructeur.

26 votes

Si vous allez complètement changer votre réponse, je vous suggère de le mentionner dans la réponse. Sinon, cela semble très étrange lorsque des personnes ont souligné pourquoi votre réponse originale n'avait aucun sens :-)

1 votes

Oui, je n'avais pas remarqué cette méthode. Merci, cela semble être la meilleure façon de procéder. Je vais la tester maintenant et si elle fonctionne correctement, j'accepterai la réponse.

64voto

Buhake Sindi Points 38654
String value = "1,000,000,000.999999999999999";
BigDecimal money = new BigDecimal(value.replaceAll(",", ""));
System.out.println(money);

Code complet pour prouver qu'aucun NumberFormatException est lancé :

import java.math.BigDecimal;

public class Tester {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String value = "1,000,000,000.999999999999999";
        BigDecimal money = new BigDecimal(value.replaceAll(",", ""));
        System.out.println(money);
    }
}

Sortie

1000000000.999999999999999

0 votes

@Steve McLeod....nope, je viens de le tester.... ma valeur est de 1000000000.999999999999999

11 votes

Essayez avec la locale GERMAN, et 1.000.000.000,999999999999

0 votes

@#TofuBeer.... l'exemple était 1,000,000,000.999999999999999. Si je devais m'adapter à votre situation locale, je devrais remplacer tous les points par des espaces.....

22voto

Ebith Points 61

L'exemple de code suivant fonctionne bien (la locale doit être obtenue dynamiquement).

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.DecimalFormat;
import java.text.ParsePosition;
import java.util.Locale;

class TestBigDecimal {
    public static void main(String[] args) {

        String str = "0,00";
        Locale in_ID = new Locale("in","ID");
        //Locale in_ID = new Locale("en","US");

        DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance(in_ID);
        nf.setParseBigDecimal(true);

        BigDecimal bd = (BigDecimal)nf.parse(str, new ParsePosition(0));

        System.out.println("bd value : " + bd);
    }
}

6voto

TofuBeer Points 32441

Le code pourrait être plus propre, mais cela semble faire l'affaire pour différentes langues.

import java.math.BigDecimal;
import java.text.DecimalFormatSymbols;
import java.util.Locale;

public class Main
{
    public static void main(String[] args)
    {
        final BigDecimal numberA;
        final BigDecimal numberB;

        numberA = stringToBigDecimal("1,000,000,000.999999999999999", Locale.CANADA);
        numberB = stringToBigDecimal("1.000.000.000,999999999999999", Locale.GERMANY);
        System.out.println(numberA);
        System.out.println(numberB);
    }

    private static BigDecimal stringToBigDecimal(final String formattedString,
                                                 final Locale locale)
    {
        final DecimalFormatSymbols symbols;
        final char                 groupSeparatorChar;
        final String               groupSeparator;
        final char                 decimalSeparatorChar;
        final String               decimalSeparator;
        String                     fixedString;
        final BigDecimal           number;

        symbols              = new DecimalFormatSymbols(locale);
        groupSeparatorChar   = symbols.getGroupingSeparator();
        decimalSeparatorChar = symbols.getDecimalSeparator();

        if(groupSeparatorChar == '.')
        {
            groupSeparator = "\\" + groupSeparatorChar;
        }
        else
        {
            groupSeparator = Character.toString(groupSeparatorChar);
        }

        if(decimalSeparatorChar == '.')
        {
            decimalSeparator = "\\" + decimalSeparatorChar;
        }
        else
        {
            decimalSeparator = Character.toString(decimalSeparatorChar);
        }

        fixedString = formattedString.replaceAll(groupSeparator , "");
        fixedString = fixedString.replaceAll(decimalSeparator , ".");
        number      = new BigDecimal(fixedString);

        return (number);
    }
}

3voto

jjnguy Points 62123

Voici comment je m'y prendrais :

public String cleanDecimalString(String input, boolean americanFormat) {
    if (americanFormat)
        return input.replaceAll(",", "");
    else
        return input.replaceAll(".", "");
}

Évidemment, si cela devait être intégré dans un code de production, ce ne serait pas aussi simple.

Je ne vois aucun problème à simplement supprimer les virgules de la chaîne.

0 votes

Et si la chaîne n'est pas au format américain ? En Allemagne, ce serait 1.000.000.000.999999999999999.

1 votes

Le principal problème ici est que les chiffres peuvent provenir de différentes sources, chacune ayant son propre format. La meilleure façon de procéder dans cette situation serait donc de définir un "format de nombre" pour chacune des sources. Je ne peux pas le faire avec de simples remplacements car une source peut avoir le format "123 456 789" et l'autre "123.456.789".

0 votes

Je vois que vous redéfinissez silencieusement le terme "méthode en une ligne"... ;-)

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