2009-02-09 17 views
8

C'è un modo per utilizzare DecimalFormat (o qualche altro formattatore standard) per formattare i numeri in questo modo:Java: il numero formato in milioni

1.000.000 => 1,00M

1.234.567 => 1.23m

1.234.567,89 mille => 1234.57M

Fondamentalmente dividendo un numero da 1 milione, mantenendo 2 decimali, e battendosi una 'M' sull'estremità. Ho pensato di creare una nuova sottoclasse di NumberFormat ma sembra più complicata di quanto immaginassi.

Sto scrivendo un'API che ha un metodo formato che assomiglia a questo:

public String format(double value, Unit unit); // Unit is an enum 

Internamente, io sono la mappatura oggetti Unità a NumberFormatters. L'implementazione è qualcosa di simile:

public String format(double value, Unit unit) 
{ 
    NumberFormatter formatter = formatters.get(unit); 
    return formatter.format(value); 
} 

Si noti che a causa di questo, non posso aspettare il cliente di dividere per 1 milione, e non posso semplicemente usare String.Format() senza avvolgendolo in un NumberFormatter.

+0

Vuoi gestire M (EGA) soltanto, o anche (G) IgA, (T) era , eccetera? –

+0

In realtà rappresenta un volume di sicurezza, quindi è M (illions) e potenzialmente B (illions) ma sarò felice solo con il M. –

+0

[Questa domanda correlata] (http://stackoverflow.com/q/4753251/ 983430) ha ricevuto molta attenzione di recente (a causa di una taglia). –

risposta

17
String.format("%.2fM", theNumber/ 1000000.0); 

Per ulteriori informazioni vedere il String.format javadocs.

+0

Solo nel caso: utilizzare 1.000.000,0 invece. –

+0

Minor nitpick, sembra che il suo codice stia usando long o ints in modo da poter fare a meno dell'aritmetica in virgola mobile: – wds

+0

Se lascio la matematica in virgola mobile, verrebbe lasciato un intero numero, senza cifre decimali. Abbiamo bisogno di almeno 2. – jjnguy

0

Dai uno sguardo allo ChoiseFormat.

Un modo più semplice sarebbe utilizzare un wrapper diviso automaticamente per 1m.

+0

Ho dato un'occhiata ai documenti ma non sono sicuro di come mi possa aiutare qui. Sembra che ChoiceFormat contenga fondamentalmente un mucchio di formati e in qualche modo corrisponda all'input con uno di questi sottoformati. Penso che voglio che tutti gli input siano gestiti allo stesso modo. –

3

Ecco una sottoclasse di NumberFormat che ho montato. Sembra che fa il lavoro, ma non sono del tutto sicuro che sia il modo migliore:

private static final NumberFormat MILLIONS = new NumberFormat() 
{ 
    private NumberFormat LOCAL_REAL = new DecimalFormat("#,##0.00M"); 

    public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) 
    { 
     double millions = number/1000000D; 
     if(millions > 0.1) LOCAL_REAL.format(millions, toAppendTo, pos); 

     return toAppendTo; 
    } 

    public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) 
    { 
     return format((double) number, toAppendTo, pos); 
    } 

    public Number parse(String source, ParsePosition parsePosition) 
    { 
     throw new UnsupportedOperationException("Not implemented..."); 
    } 
}; 
+0

Mi piace la soluzione di Outlaw, specialmente perché può anche creare la formattazione "leggibile" di k/M/G senza che l'utente di questa API debba fare calcoli. Ottiene sempre il numero più breve possibile. 999.99k 999.99M 999.99G 999.99T – eckes

3

Perché non semplicemente?

DecimalFormat df = new DecimalFormat("0.00M"); 
System.out.println(df.format(n/1000000)); 
+0

La divisione deve essere incapsulata all'interno del formattatore. Suppongo che aggiornerò la domanda per spiegare più chiaramente il problema che sto avendo. –

4

Si noti che se si dispone di un BigDecimal, è possibile utilizzare il metodo movePointLeft:

new DecimalFormat("#.00").format(value.movePointLeft(6));