J'essaie de lire des valeurs BigDecimal à partir de la chaîne. Disons que j'ai cette chaîne: "1 000 000 000,99999999999999999" et que je veux obtenir un BigDecimal. Quel est le moyen de le faire?
Tout d'abord, je n'aime pas les solutions utilisant le remplacement de chaînes (remplacer les virgules, etc.). Je pense qu'il devrait y avoir un formateur soigné pour faire ce travail pour moi.
J'ai trouvé une classe DecimalFormatter, mais comme elle fonctionne par double, une énorme précision est perdue.
Alors, comment puis-je le faire?
Départ setParseBigDecimal
dans DecimalFormat. Avec ce setter, parse
vous retournera un BigDecimal.
String value = "1,000,000,000.999999999999999";
BigDecimal money = new BigDecimal(value.replaceAll(",", ""));
System.out.println(money);
Code complet pour prouver qu'aucun NumberFormatException
n'est jeté:
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
10000000009999999999999999
L'exemple de code suivant fonctionne bien (les paramètres régionaux doivent être obtenus de manière dynamique)
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);
}
}
Le code pourrait être plus propre, mais cela semble faire l'affaire pour différents paramètres régionaux.
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);
}
}
J'avais besoin d'une solution pour convertir une chaîne en BigDecimal sans connaître les paramètres régionaux et être indépendant de ces paramètres. Je ne pouvais pas trouver de solution standard à ce problème, j'ai donc écrit ma propre méthode d'assistance. Peut-être que cela aide aussi quelqu'un d'autre:
Mise à jour: Attention! Cette méthode d'assistance ne fonctionne qu'avec les nombres décimaux, donc les nombres qui ont toujours un point décimal! Sinon, la méthode d'assistance pourrait donner un résultat incorrect pour les nombres compris entre 1000 et 999999 (plus/moins). Merci à bezmax pour sa grande contribution!
static final String EMPTY = "";
static final String POINT = '.';
static final String COMMA = ',';
static final String POINT_AS_STRING = ".";
static final String COMMA_AS_STRING = ",";
/**
* Converts a String to a BigDecimal.
* if there is more than 1 '.', the points are interpreted as thousand-separator and will be removed for conversion
* if there is more than 1 ',', the commas are interpreted as thousand-separator and will be removed for conversion
* the last '.' or ',' will be interpreted as the separator for the decimal places
* () or - in front or in the end will be interpreted as negative number
*
* @param value
* @return The BigDecimal expression of the given string
*/
public static BigDecimal toBigDecimal(final String value) {
if (value != null){
boolean negativeNumber = false;
if (value.containts("(") && value.contains(")"))
negativeNumber = true;
if (value.endsWith("-") || value.startsWith("-"))
negativeNumber = true;
String parsedValue = value.replaceAll("[^0-9\\,\\.]", EMPTY);
if (negativeNumber)
parsedValue = "-" + parsedValue;
int lastPointPosition = parsedValue.lastIndexOf(POINT);
int lastCommaPosition = parsedValue.lastIndexOf(COMMA);
//handle '1423' case, just a simple number
if (lastPointPosition == -1 && lastCommaPosition == -1)
return new BigDecimal(parsedValue);
//handle '45.3' and '4.550.000' case, only points are in the given String
if (lastPointPosition > -1 && lastCommaPosition == -1){
int firstPointPosition = parsedValue.indexOf(POINT);
if (firstPointPosition != lastPointPosition)
return new BigDecimal(parsedValue.replace(POINT_AS_STRING, EMPTY));
else
return new BigDecimal(parsedValue);
}
//handle '45,3' and '4,550,000' case, only commas are in the given String
if (lastPointPosition == -1 && lastCommaPosition > -1){
int firstCommaPosition = parsedValue.indexOf(COMMA);
if (firstCommaPosition != lastCommaPosition)
return new BigDecimal(parsedValue.replace(COMMA_AS_STRING, EMPTY));
else
return new BigDecimal(parsedValue.replace(COMMA, POINT));
}
//handle '2.345,04' case, points are in front of commas
if (lastPointPosition < lastCommaPosition){
parsedValue = parsedValue.replace(POINT_AS_STRING, EMPTY);
return new BigDecimal(parsedValue.replace(COMMA, POINT));
}
//handle '2,345.04' case, commas are in front of points
if (lastCommaPosition < lastPointPosition){
parsedValue = parsedValue.replace(COMMA_AS_STRING, EMPTY);
return new BigDecimal(parsedValue);
}
throw new NumberFormatException("Unexpected number format. Cannot convert '" + value + "' to BigDecimal.");
}
return null;
}
Bien sûr, j'ai testé la méthode:
@Test(dataProvider = "testBigDecimals")
public void toBigDecimal_defaultLocaleTest(String stringValue, BigDecimal bigDecimalValue){
BigDecimal convertedBigDecimal = DecimalHelper.toBigDecimal(stringValue);
Assert.assertEquals(convertedBigDecimal, bigDecimalValue);
}
@DataProvider(name = "testBigDecimals")
public static Object[][] bigDecimalConvertionTestValues() {
return new Object[][] {
{"5", new BigDecimal(5)},
{"5,3", new BigDecimal("5.3")},
{"5.3", new BigDecimal("5.3")},
{"5.000,3", new BigDecimal("5000.3")},
{"5.000.000,3", new BigDecimal("5000000.3")},
{"5.000.000", new BigDecimal("5000000")},
{"5,000.3", new BigDecimal("5000.3")},
{"5,000,000.3", new BigDecimal("5000000.3")},
{"5,000,000", new BigDecimal("5000000")},
{"+5", new BigDecimal("5")},
{"+5,3", new BigDecimal("5.3")},
{"+5.3", new BigDecimal("5.3")},
{"+5.000,3", new BigDecimal("5000.3")},
{"+5.000.000,3", new BigDecimal("5000000.3")},
{"+5.000.000", new BigDecimal("5000000")},
{"+5,000.3", new BigDecimal("5000.3")},
{"+5,000,000.3", new BigDecimal("5000000.3")},
{"+5,000,000", new BigDecimal("5000000")},
{"-5", new BigDecimal("-5")},
{"-5,3", new BigDecimal("-5.3")},
{"-5.3", new BigDecimal("-5.3")},
{"-5.000,3", new BigDecimal("-5000.3")},
{"-5.000.000,3", new BigDecimal("-5000000.3")},
{"-5.000.000", new BigDecimal("-5000000")},
{"-5,000.3", new BigDecimal("-5000.3")},
{"-5,000,000.3", new BigDecimal("-5000000.3")},
{"-5,000,000", new BigDecimal("-5000000")},
{null, null}
};
}
Voici comment je le ferais:
public String cleanDecimalString(String input, boolean americanFormat) {
if (americanFormat)
return input.replaceAll(",", "");
else
return input.replaceAll(".", "");
}
Évidemment, si cela se passait dans le code de production, ce ne serait pas si simple.
Je ne vois aucun problème à simplement supprimer les virgules de la chaîne.
_resultString = subjectString.replaceAll("[^.\\d]", "");
_
supprime tous les caractères sauf les chiffres et le point de votre chaîne.
Pour que cela prenne en compte les paramètres régionaux, vous pouvez utiliser getDecimalSeparator()
à partir de Java.text.DecimalFormatSymbols
. Je ne connais pas Java, mais cela pourrait ressembler à ceci:
_sep = getDecimalSeparator()
resultString = subjectString.replaceAll("[^"+sep+"\\d]", "");
_
S'il vous plaît essayez cela sa travaille pour moi
BigDecimal bd ;
String value = "2000.00";
bd = new BigDecimal(value);
BigDecimal currency = bd;
Ancien sujet, mais le plus simple est peut-être d'utiliser Apache commons NumberUtils qui a une méthode createBigDecimal (valeur de chaîne) ....
Je suppose (espère) que cela prend en compte les lieux, sinon ce serait plutôt inutile.