Formattazione dei numeri in Java

1. Panoramica

In questo tutorial, esamineremo diversi approcci alla formattazione dei numeri in Java e come implementarli.

2. Formattazione di base dei numeri con il formato String #

Il metodo di formattazione String # è molto utile per la formattazione dei numeri. Il metodo accetta due argomenti. Il primo argomento descrive il modello su quante cifre decimali vogliamo vedere, e il secondo argomento è il valore dato:

double value = 4.2352989244d; assertThat(String.format("%.2f", value)).isEqualTo("4.24"); assertThat(String.format("%.3f", value)).isEqualTo("4.235");

3. Formattazione decimale mediante arrotondamento

In Java, abbiamo due tipi primitivi che rappresentano i numeri decimali - float e decimali :

double myDouble = 7.8723d; float myFloat = 7.8723f;

Il numero di cifre decimali può variare a seconda delle operazioni eseguite. Nella maggior parte dei casi, siamo interessati solo alla prima coppia di cifre decimali. Diamo un'occhiata ad alcuni modi per formattare un decimale arrotondando.

3.1. Utilizzo di BigDecimal per la formattazione dei numeri

La classe BigDecimal fornisce metodi per arrotondare a un numero specificato di posizioni decimali. Creiamo un metodo di supporto che restituirà un doppio, arrotondato al numero di posizioni desiderato:

public static double withBigDecimal(double value, int places) { BigDecimal bigDecimal = new BigDecimal(value); bigDecimal = bigDecimal.setScale(places, RoundingMode.HALF_UP); return bigDecimal.doubleValue(); }

Iniziamo con una nuova istanza di BigDecimal con il nostro valore decimale originale. Quindi, impostando la scala, forniamo il numero di cifre decimali che vogliamo e come vogliamo arrotondare il nostro numero . L'utilizzo di questo metodo ci consente di formattare facilmente un valore doppio :

double D = 4.2352989244d; assertThat(withBigDecimal(D, 2)).isEqualTo(4.24); assertThat(withBigDecimal(D, 3)).isEqualTo(4.235);

3.2. Utilizzando Math # round

Possiamo anche sfruttare i metodi statici della classe Math per arrotondare un valore double a una posizione decimale specificata. In questo caso, possiamo regolare il numero di cifre decimali moltiplicando e successivamente dividendo per 10 ^ n . Controlliamo il nostro metodo di supporto:

public static double withMathRound(double value, int places) { double scale = Math.pow(10, places); return Math.round(value * scale) / scale; }
assertThat(withMathRound(D, 2)).isEqualTo(4.24); assertThat(withMathRound(D, 3)).isEqualTo(4.235);

Tuttavia, questo metodo è consigliato solo in casi particolari poiché a volte l'output potrebbe essere arrotondato in modo diverso come previsto prima della stampa.

Questo perché Math # round sta troncando il valore . Vediamo come può succedere:

System.out.println(withMathRound(1000.0d, 17)); // Gives: 92.23372036854776 !! System.out.println(withMathRound(260.775d, 2)); // Gives: 260.77 instead of expected 260.78 

E così, il metodo è elencato solo per scopi di apprendimento.

4. Formattazione di diversi tipi di numeri

In alcuni casi particolari, potremmo voler formattare un numero per un tipo specifico come valuta, numero intero grande o percentuale.

4.1. Formattazione di numeri interi grandi con virgole

Ogni volta che abbiamo un numero intero grande nella nostra applicazione, potremmo volerlo visualizzare con virgole, utilizzando DecimalFormat con uno schema predefinito:

public static String withLargeIntegers(double value) { DecimalFormat df = new DecimalFormat("###,###,###"); return df.format(value); } int value = 123456789; assertThat(withLargeIntegers(value)).isEqualTo("123,456,789");

4.2. Riempire un numero

In alcuni casi, potremmo voler riempire un numero con zeri per una lunghezza specificata. Qui possiamo usare il metodo di formato String # , come descritto in precedenza:

public static String byPaddingZeros(int value, int paddingLength) { return String.format("%0" + paddingLength + "d", value); } int value = 1; assertThat(byPaddingOutZeros(value, 3)).isEqualTo("001");

4.3. Formattazione dei numeri con due zeri dopo il decimale

Per poter stampare un dato numero con due zeri dopo il punto decimale, useremo ancora una volta la classe DecimalFormat con uno schema predefinito:

public static double withTwoDecimalPlaces(double value) { DecimalFormat df = new DecimalFormat("#.00"); return new Double(df.format(value)); } int value = 12; assertThat(withTwoDecimalPlaces(value)).isEqualTo(12.00);

In questo caso, abbiamo creato un nuovo formato con un pattern che specifica due zeri dopo il punto decimale .

4.4. Formattazione e percentuali

Di tanto in tanto potremmo aver bisogno di visualizzare le percentuali.

In questo caso, possiamo utilizzare il metodo NumberFormat # getPercentInstance . Questo metodo ci consente di fornire una Locale per stampare il valore in un formato corretto per il Paese specificato:

public static String forPercentages(double value, Locale locale) { NumberFormat nf = NumberFormat.getPercentInstance(locale); return nf.format(value); } double value = 25f / 100f; assertThat(forPercentages(value, new Locale("en", "US"))).isEqualTo("25%");

4.5. Formattazione del numero di valuta

Un modo comune per memorizzare le valute nella nostra applicazione è utilizzare BigDecimal . E se volessimo mostrarli all'utente? In questo caso, possiamo usare la classe NumberFormat :

public static String currencyWithChosenLocalisation(double value, Locale locale) { NumberFormat nf = NumberFormat.getCurrencyInstance(locale); return nf.format(value); }

Otteniamo l'istanza di valuta per una data Locale e quindi chiamiamo semplicemente il metodo di formato con il valore. Il risultato è il numero visualizzato come valuta per il paese specificato:

double value = 23_500; assertThat(currencyWithChosenLocalisation(value, new Locale("en", "US"))).isEqualTo("$23,500.00"); assertThat(currencyWithChosenLocalisation(value, new Locale("zh", "CN"))).isEqualTo("¥23,500.00"); assertThat(currencyWithChosenLocalisation(value, new Locale("pl", "PL"))).isEqualTo("23 500 zł");

5. Casi d'uso di formattazione avanzata

DecimalFormat è uno dei modi più diffusi per formattare un numero decimale in Java. Simile agli esempi precedenti scriveremo un metodo di supporto:

public static double withDecimalFormatLocal(double value) { DecimalFormat df = (DecimalFormat) NumberFormat.getNumberInstance(Locale.getDefault()); return new Double(df.format(value)); }

Il nostro tipo di formattazione otterrà l'impostazione predefinita per una data localizzazione.

La formattazione decimale viene gestita in modo diverso nei diversi paesi utilizzando i loro sistemi numerici. Ad esempio il carattere di raggruppamento (virgola negli Stati Uniti, ma spazio o punto in altre lingue), la dimensione del raggruppamento (tre negli Stati Uniti e la maggior parte delle lingue, ma diverso in India) o il carattere decimale (punto negli Stati Uniti, ma un virgola in altre lingue).

double D = 4.2352989244d; assertThat(withDecimalFormatLocal(D)).isEqualTo(4.235);

Possiamo anche estendere questa funzionalità per fornire alcuni modelli specifici:

public static double withDecimalFormatPattern(double value, int places) { DecimalFormat df2 = new DecimalFormat("#,###,###,##0.00"); DecimalFormat df3 = new DecimalFormat("#,###,###,##0.000"); if (places == 2) return new Double(df2.format(value)); else if (places == 3) return new Double(df3.format(value)); else throw new IllegalArgumentException(); } assertThat(withDecimalFormatPattern(D, 2)).isEqualTo(4.24); assertThat(withDecimalFormatPattern(D, 3)).isEqualTo(4.235);

Qui permettiamo al nostro utente di configurare DecimalFormat dal modello scelto in base al numero di spazi.

6. Conclusione

In questo articolo, abbiamo esaminato brevemente diversi modi di formattazione dei numeri in Java. Come possiamo vedere, non esiste un modo migliore per farlo. Potrebbero essere seguiti molti approcci poiché ognuno di essi ha le proprie caratteristiche.

Come sempre, il codice per questi esempi è disponibile su GitHub.