i18n checklist java text localization

checklist - ¿Cómo formatea un porcentaje fraccional con java.text.MessageFormat?



i18n java (6)

¿Te das cuenta de que "expectedResult == actualResult" siempre será falso, ¿verdad?

De todos modos, la mejor solución que puedo encontrar es configurar el formateador de forma explícita. Este es el código que probé:

String expectedResult = "12.5%"; double fraction = 0.125; MessageFormat fmt = new MessageFormat("{0,number,percent}"); NumberFormat nbFmt = NumberFormat.getPercentInstance(); nbFmt.setMaximumFractionDigits(1); // or 2, or however many you need fmt.setFormatByArgumentIndex(0, nbFmt); String actualResult = fmt.format(new Object[] {fraction}); assert expectedResult.equals(actualResult) : actualResult +" is getting rounded off";

Mis porcentajes se truncan con la función predeterminada java.text.MessageFormat, ¿cómo formatear un porcentaje sin perder precisión?

Ejemplo:

String expectedResult = "12.5%"; double fraction = 0.125; String actualResult = MessageFormat.format("{0,number,percent}", fraction); assert expectedResult.equals(actualResult) : actualResult +" should be formatted as "+expectedResult;


Creo que la forma correcta de hacerlo es la siguiente:

NumberFormat percentFormat = NumberFormat.getPercentInstance(); percentFormat.setMaximumFractionDigits(1); String result = percentFormat.format(0.125);

También tiene en cuenta la internalización. Por ejemplo, en mi máquina con locale húngara obtuve "12,5%" como se esperaba. Inicializar percentFormat como NumberFormat.getPercentInstance(Locale.US) da "12.5%", por supuesto.


Mi solución representa tantos dígitos fraccionarios como la escala se estableció en Número dado. Unidad probada con muchos tipos primitivos y Number .

/** * Formats the given Number as percentage with necessary precision. * This serves as a workaround for {@link NumberFormat#getPercentInstance()} which does not renders fractional * digits. * * @param number * @param locale * * @return */ public static String formatPercentFraction(final Number number, final Locale locale) { if (number == null) return null; // get string representation with dot final String strNumber = NumberFormat.getNumberInstance(Locale.US).format(number.doubleValue()); // create exact BigDecimal and convert to get scale final BigDecimal dNumber = new BigDecimal(strNumber).multiply(new BigDecimal(100)); final NumberFormat percentScaleFormat = NumberFormat.getPercentInstance(locale); percentScaleFormat.setMaximumFractionDigits(Math.max(0, dNumber.scale())); // convert back for locale percent formatter return percentScaleFormat.format(dNumber.multiply(new BigDecimal(0.01))); }


Qué tal si

DecimalFormat f = new DecimalFormat( "###.#" ); System.out.println( f.format( 12.5 ) );

El formato char ''#'' no imprime un 0 como ausente. Entonces 12.5 -> "12.5", 12.0 -> "12", no "12.0". Por supuesto, puede configurar su formateador con, por ejemplo, "###, ###. ##", el lugar centésimo solo aparecerá si necesita la precisión.


Se ve como esto:

String actualResult = MessageFormat.format("{0,number,#.##%}", fraction);

... está trabajando.

EDITAR: para ver cómo se interpretan los # ''sy%'' s, consulte el javadoc de java.text.DecimalFormat.

EDIT 2: Y sí, es seguro para la internacionalización. El punto en la cadena de formato se interpreta como un separador decimal, no como un punto codificado. :-)


Si la internacionalización es una preocupación:

// get locale from somewhere. default is usually a bad idea, especially // if running in a app server Locale locale = Locale.getDefault(); NumberFormat fmt = NumberFormat.getPercentInstance(locale); // the question requires 1 digit for fractional part // therefore set both, minimum and maximum digit count fmt.setMinimumFractionDigits(1); fmt.setMaximumFractionDigits(1); // set grouping, if you expect large values // notabene: not all languages use 3 digits per group fmt.setGroupingUsed(true); // output the example of the original question System.out.println(fmt.format(0.125));

El formateador de porcentaje de porcentaje agrega un espacio y el signo de porcentaje a la salida en las configuraciones regionales que conozco. No sé si la posición del signo de porcentaje está antes de los dígitos en otras configuraciones regionales (por ejemplo, configuraciones de derecha a izquierda).