Tomando en consideración lo que ha dicho He modificado un poco mi código para cubrir diferentes configuraciones regionales. La clave estaba llevando una cadena de valor en un formato localizado a un Doble que se redondeaba en función de la cadena de formato.
La cadena de formato siempre es un formato basado en el Reino Unido con los separadores decimales especificados como "." y miles de separadores especificados como ",".
Estoy usando DecimalFormat para analizar inicialmente el formato localizado basado en una configuración regional especificada. Esto da un doble equivalente de la cadena correctamente. Luego uso un BigDecimal para manejar el redondeo. Puedo obtener el número de decimales de la instancia DecimalFormat y llamar a setScale en BigDecimal para realizar el redondeo.
La estructura del código inicial se ha modificado para permitirle ver lo que sucede en diferentes circunstancias de la configuración regional, gracias a @ RD01 para tener en cuenta la importancia de otras configuraciones regionales.
ahora tengo código como sigue:
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("");
}
Esto produce el siguiente resultado:
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
¿Realmente quiere tratar de hacer esto? Debido a la pérdida de precisión en la conversión de base 10 a binario (la representación interna), es posible que no obtenga lo que espera. – Raedwald