Je veux être capable de convertir une chaîne en Double étant donné un nombre de décimales dans une chaîne de format. Donc "###, ## 0.000" devrait me donner un Double à 3 décimales.
Edit - ajout de plus d'informations à ce qui se passe
L'utilisateur entre la valeur dans l'interface utilisateur - qui est entrée dans une chaîne. La règle est que cette valeur est limitée à 3 décimales. Le code sous-jacent stocke la valeur dans la base de données qui est ensuite utilisée dans un calcul. Par conséquent, les décimales suivantes feront que les calculs seront légèrement à la hauteur des attentes.
J'ai le code suivant:
try {
// output current locale we are running under (this happens to be "nl_BE")
System.out.println( "Current Locale is " + Locale.getDefault().toString() );
// number in Central European Format with a format string specified in UK format
String numberCE = "1,234567"; // 1.234567
String formatUK = "###,##0.000";
// do the format
DecimalFormat formatterUK = new DecimalFormat( formatUK );
Double valCEWithUKFormat = formatterUK.parse( numberCE ).doubleValue();
// I want the number to DPs in the format string!!!
System.out.println( "CE Value " + numberCE + " in UK format (" + formatUK + ") is "
+ valCEWithUKFormat );
} catch( ParseException ex ) {
System.out.println("Cannot parse number");
}
}
Le DecimalFormat semble ignorer la chaîne de format et me donne la chaîne complète en tant que Double de 1.234567.
DecimalFormat peut-il être obligé d'utiliser la chaîne de format lors de l'analyse? Est-ce que je manque quelque chose?
À votre santé,
Andez
Prenant en compte ce que vous avez dit, j'ai légèrement modifié mon code pour couvrir différents endroits. La clé prenait une chaîne de valeur dans un format localisé en un fichier Double arrondi en fonction de la chaîne de format.
La chaîne de formatage est toujours un format basé au Royaume-Uni avec les séparateurs décimaux spécifiés comme "." et mille séparateurs spécifiés comme ",".
J'utilise DecimalFormat pour analyser initialement le format localisé en fonction des paramètres régionaux spécifiés. Cela donne un double équivalent de la chaîne correctement. J'utilise ensuite un BigDecimal pour gérer l'arrondi. Je peux obtenir le nombre de décimales à partir de l'instance DecimalFormat et appeler setScale sur BigDecimal pour effectuer l'arrondi.
La structure de code initiale a été modifiée pour vous permettre de voir ce qui se passe dans différentes circonstances de paramètres régionaux, grâce à @ RD01 pour avoir noté l’importance des autres paramètres régionaux.
J'ai maintenant le code comme suit:
private void runTests3() {
// output current locale we are running under
System.out.println( "Current Locale is " + Locale.getDefault().toString() );
// number in Central European Format with a format string specified in UK format
String numbersInEuropeanFormatString[] = new String[] { "1.000,234567", "1,2345678", "1.222.333,234567" };
String formatUK = "###,##0.0000";
// output numbers using the german locale
System.out.println("Output numbers using the German locale\n");
for(String num : numbersInEuropeanFormatString ) {
formatNumberAsDouble(num, formatUK, Locale.GERMAN);
}
// output numbers using the UK locale.
// this should return unexpected results as the number is in European format
System.out.println("Output numbers using the UK locale\n");
for(String num : numbersInEuropeanFormatString ) {
formatNumberAsDouble(num, formatUK, Locale.UK);
}
// output numbers using new DecimalFormat( formatUK ) - no locale specified
System.out.println("\n\nOutput numbers using new DecimalFormat( " + formatUK + " )\n");
for(String num : numbersInEuropeanFormatString ) {
formatNumberAsDouble( num, formatUK, null);
}
}
private void formatNumberAsDouble(String value, String format, Locale locale) {
NumberFormat formatter;
int decimalPlaces;
// create the formatter based on the specified locale
if( locale != null ) {
formatter = NumberFormat.getNumberInstance(locale);
// creating the above number format does not take in the format string
// so create a new one that we won't use at all just to get the
// decimal places in it
decimalPlaces = (new DecimalFormat(format)).getMaximumFractionDigits();
} else {
formatter = new DecimalFormat( format );
decimalPlaces = formatter.getMaximumFractionDigits();
}
// get the result as number
Double result = null;
try {
result = formatter.parse( value ).doubleValue();
} catch( ParseException ex ) {
// not bothered at minute
}
// round the Double to the precision specified in the format string
BigDecimal bd = new BigDecimal(result );
Double roundedValue = bd.setScale( decimalPlaces, RoundingMode.HALF_UP ).doubleValue();
// output summary
System.out.println("\tValue = " + value);
System.out.println( locale == null ? "\tLocale not specified" : "\tLocale = " + locale.toString());
System.out.println( format == null || format.length() == 0 ? "\tFormat = Not specified" : "\tFormat = " + format);
System.out.println("\tResult (Double) = " + result);
System.out.println("\tRounded Result (Double) (" + decimalPlaces + "dp) = " + roundedValue);
System.out.println("");
}
Cela produit la sortie suivante:
Current Locale is nl_BE
Output numbers using the German locale
Value = 1.000,234567
Locale = de
Format = ###,##0.0000
Result (Double) = 1000.234567
Rounded Result (Double) (4dp) = 1000.2346
Value = 1,2345678
Locale = de
Format = ###,##0.0000
Result (Double) = 1.2345678
Rounded Result (Double) (4dp) = 1.2346
Value = 1.222.333,234567
Locale = de
Format = ###,##0.0000
Result (Double) = 1222333.234567
Rounded Result (Double) (4dp) = 1222333.2346
Output numbers using the UK locale
Value = 1.000,234567
Locale = en_GB
Format = ###,##0.0000
Result (Double) = 1.0
Rounded Result (Double) (4dp) = 1.0
Value = 1,2345678
Locale = en_GB
Format = ###,##0.0000
Result (Double) = 1.2345678E7
Rounded Result (Double) (4dp) = 1.2345678E7
Value = 1.222.333,234567
Locale = en_GB
Format = ###,##0.0000
Result (Double) = 1.222
Rounded Result (Double) (4dp) = 1.222
Output numbers using new DecimalFormat( ###,##0.0000 )
Value = 1.000,234567
Locale not specified
Format = ###,##0.0000
Result (Double) = 1000.234567
Rounded Result (Double) (4dp) = 1000.2346
Value = 1,2345678
Locale not specified
Format = ###,##0.0000
Result (Double) = 1.2345678
Rounded Result (Double) (4dp) = 1.2346
Value = 1.222.333,234567
Locale not specified
Format = ###,##0.0000
Result (Double) = 1222333.234567
Rounded Result (Double) (4dp) = 1222333.2346
DecimalFormat est utilisé à deux fins distinct : analyser une entrée et formater une sortie. Si vous voulez faire les deux, vous devrez utiliser l'objet de format deux fois.
Si vous souhaitez prendre cette valeur et formater la sortie en limitant le nombre de chiffres significatifs, vous devez utiliser à nouveau l'objet de formatage. Cette fois, il utilise vos règles de formatage pour créer une chaîne de sortie à partir d'une valeur numérique:
String output = formatterUK.format(valCEWithUKFormat.doubleValue() );
Cela vous donnera la sortie de 1,235
Il semble que vous souhaitiez que cette valeur numérique soit présentée au format 1.235. Pour ce faire, vous devez formater la sortie en utilisant des paramètres régionaux spécifiques (si le vôtre utilise un format différent).
CEPENDANT, je recommanderais d'aborder ce problème différemment:
String text = "1,234567";
NumberFormat nf_in = NumberFormat.getNumberInstance(Locale.GERMANY);
double val = nf_in.parse(text).doubleValue();
NumberFormat nf_out = NumberFormat.getNumberInstance(Locale.UK);
nf_out.setMaximumFractionDigits(3);
String output = nf_out.format(val);
Quelques notes:
La restriction de décimales dans DecimalFormat est vraiment destinée à être utilisée dans la méthode format()
et n'a pas beaucoup d'effet dans la méthode parse()
.
Pour obtenir ce que vous voulez, vous avez besoin de ceci:
try {
// output current locale we are running under (this happens to be "nl_BE")
System.out.println("Current Locale is " + Locale.getDefault().toString());
// number in Central European Format with a format string specified in UK format
String numberCE = "1,234567"; // 1.234567
String formatUK = "###,##0.000";
// do the format
DecimalFormat formatterUK = new DecimalFormat(formatUK);
Double valCEWithUKFormat = formatterUK.parse(numberCE).doubleValue();
// first convert to UK format string
String numberUK = formatterUK.format(valCEWithUKFormat);
// now parse that string to a double
valCEWithUKFormat = formatterUK.parse(numberUK).doubleValue();
// I want the number to DPs in the format string!!!
System.out.println("CE Value " + numberCE + " in UK format (" + formatUK + ") is " + valCEWithUKFormat);
} catch (ParseException ex) {
System.out.println("Cannot parse number");
}
Vous devez d’abord obtenir le numéro sous forme de chaîne de format UK, puis l’analyser à l’aide du programme de formatage UK. Cela vous donnera le résultat que vous recherchez. NB, cela arrondira le nombre à 3 décimales, pas tronquer.
En passant, je suis un peu surpris que votre formateur britannique puisse analyser le numéro de format CE. Vous devriez vraiment analyser le numéro d'origine avec un analyseur au format CE.
Sûr que vous pouvez. Essayez de lancer ceci:
String in = "1,234567";
System.out.println(NumberFormat.getNumberFormat(new Locale("fr", "FR")).parse(in));
System.out.println(NumberFormat.getNumberFormat(new Locale("en", "GB")).parse(in));
Clairement, ils produisent une sortie différente, la première lecture 1.234567
et la seconde 1234567
. Peut-être qu'il y a quelque chose qui ne va pas avec votre modèle? Quoi qu’il en soit, la dernière ligne serait le moyen privilégié d’obtenir le format standard UK
.