Formato de número de moneda Java


89

¿Hay alguna forma de formatear un decimal de la siguiente manera?

100   -> "100"  
100.1 -> "100.10"

Si es un número redondo, omita la parte decimal. De lo contrario, formatee con dos lugares decimales.

Respuestas:


48

Lo dudo. El problema es que 100 nunca es 100 si es un float, normalmente es 99.9999999999 o 100.0000001 o algo así.

Si desea formatearlo de esa manera, debe definir un épsilon, es decir, una distancia máxima de un número entero, y usar formato de entero si la diferencia es menor y un flotante en caso contrario.

Algo como esto haría el truco:

public String formatDecimal(float number) {
  float epsilon = 0.004f; // 4 tenths of a cent
  if (Math.abs(Math.round(number) - number) < epsilon) {
     return String.format("%10.0f", number); // sdb
  } else {
     return String.format("%10.2f", number); // dj_segfault
  }
}

8
Minor nitpick: un float puede ser exactamente 100, con un patrón de bits 0x42c80000.
Karol S

2
Sí, como dijo Karol S, muchos números PUEDEN coincidir exactamente con flotadores. Simplemente no TODOS los números. 100 es un número que se puede representar, solo debe tener en cuenta los números que no pueden ser.
csga5000

160

Recomendaría usar el paquete java.text:

double money = 100.1;
NumberFormat formatter = NumberFormat.getCurrencyInstance();
String moneyString = formatter.format(money);
System.out.println(moneyString);

Esto tiene el beneficio adicional de ser específico de la localidad.

Pero, si es necesario, trunca el String que obtienes si es un dólar entero:

if (moneyString.endsWith(".00")) {
    int centsIndex = moneyString.lastIndexOf(".00");
    if (centsIndex != -1) {
        moneyString = moneyString.substring(1, centsIndex);
    }
}

17
Nunca debe usar un doble para representar monedas. Convierta a largos y administre el punto decimal usted mismo o utilícelo BigDecimalcon un formateador. joda-money.sourceforge.net debería ser una buena biblioteca para usar una vez que esté hecho.
gpampara

5
Estoy de acuerdo con: ¡doble! = Dinero, pero no es así como se planteó la pregunta.
Duffymo

3
¿Qué quieres decir con que así es como funcionan las monedas? Puedo decir que algo cuesta $ 1, no $ 1.00 ... hay diferentes formas de mostrar las monedas (distintas de la predeterminada) y esta pregunta pregunta cómo omitir la parte decimal si es un número entero.
DD.

1
Es un problema de renderizado. Coloque la lógica en su interfaz de usuario para aceptar la moneda como una cadena y trunque el decimal y los centavos si es un dólar exacto.
Duffymo

2
De acuerdo, es por eso que recomendé usar Locale cuando escribí esto hace 5.5 años. "Pero, si es necesario, ...." es la frase clave.
duffymo

124
double amount =200.0;
Locale locale = new Locale("en", "US");      
NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(locale);
System.out.println(currencyFormatter.format(amount));

o

double amount =200.0;
System.out.println(NumberFormat.getCurrencyInstance(new Locale("en", "US"))
        .format(amount));

La mejor forma de mostrar la moneda

Salida

200,00 $

Si no desea usar el signo, use este método

double amount = 200;
DecimalFormat twoPlaces = new DecimalFormat("0.00");
System.out.println(twoPlaces.format(amount));

200,00

Esto también se puede usar (con el separador de miles)

double amount = 2000000;    
System.out.println(String.format("%,.2f", amount));          

2,000,000.00


No parece que se haga referencia a la "moneda" o se use después de declararse ... ¿hay algún efecto secundario de la línea 3? ¿O alguna razón por la que lo incluiste?
Damian

Leer más sobre [Class Locale] [1] [1]: docs.oracle.com/javase/7/docs/api/java/util/…
Thilina Dharmasena

18

No encontré ninguna buena solución después de la búsqueda en Google, solo publique mi solución para que otros puedan consultarla. use priceToString para formatear dinero.

public static String priceWithDecimal (Double price) {
    DecimalFormat formatter = new DecimalFormat("###,###,###.00");
    return formatter.format(price);
}

public static String priceWithoutDecimal (Double price) {
    DecimalFormat formatter = new DecimalFormat("###,###,###.##");
    return formatter.format(price);
}

public static String priceToString(Double price) {
    String toShow = priceWithoutDecimal(price);
    if (toShow.indexOf(".") > 0) {
        return priceWithDecimal(price);
    } else {
        return priceWithoutDecimal(price);
    }
}

Nunca dijo que fuera mejor. Él acaba de publicar su solución para que otros puedan consultarla. Lo menos que se puede decir es un agradecimiento.
Umang Desai

¿Qué pasa si quiero mostrar el precio en formato indio? Sin decimales. Formato -> ##, ##, ###
Bhuvan

En el método priceWithDecimal (Double), intente cambiar la máscara "###,###,###.00"para "###,###,##0.00"mostrar "0,00" cuando el valor sea "0"
dellasavia

1
¿Qué hará al revés para convertir la moneda formateada a Double nuevamente
Vivek Shankar

6

Si. Puede utilizar java.util.formatter . Puede utilizar una cadena de formato como "% 10.2f"


String.format()es una buena envoltura estática para eso. Sin embargo, no estoy seguro de por qué usa '10'.
Xr.

Sin ninguna orientación sobre el tamaño del número, elegí 10 Ex Recto. No sabemos si este es el precio de una barra de chocolate o de un automóvil. Creo que también puede hacer "% .2f" para dejar el tamaño total ilimitado.
dj_segfault

DD quería que se omitiera la parte decimal, si la cantidad es un número redondo de unidades monetarias.
jarnbjo

6

Estoy usando este (usando StringUtils de commons-lang):

Double qty = 1.01;
String res = String.format(Locale.GERMANY, "%.2f", qty);
String fmt = StringUtils.removeEnd(res, ",00");

Solo debe cuidar la configuración regional y la Cadena correspondiente para cortar.


5

Creo que esto es simple y claro para imprimir una moneda:

DecimalFormat df = new DecimalFormat("$###,###.##"); // or pattern "###,###.##$"
System.out.println(df.format(12345.678));

salida: $ 12,345.68

Y una de las posibles soluciones a la pregunta:

public static void twoDecimalsOrOmit(double d) {
    System.out.println(new DecimalFormat(d%1 == 0 ? "###.##" : "###.00").format(d));
}

twoDecimalsOrOmit((double) 100);
twoDecimalsOrOmit(100.1);

Salida:

100

100,10


Has perdido el sentido de la publicación. Si el número es entero, no quiero mostrar decimales.
DD.

DD. Lo siento, y corregí la respuesta de acuerdo a la pregunta.
Andrew

5

Por lo general, necesitaremos hacer lo inverso, si su campo de dinero json es un flotante, puede ser 3.1, 3.15 o solo 3.

En este caso, es posible que deba redondearlo para una visualización adecuada (y para poder usar una máscara en un campo de entrada más adelante):

floatvalue = 200.0; // it may be 200, 200.3 or 200.37, BigDecimal will take care
Locale locale = new Locale("en", "US");      
NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(locale);

BigDecimal valueAsBD = BigDecimal.valueOf(value);
    valueAsBD.setScale(2, BigDecimal.ROUND_HALF_UP); // add digits to match .00 pattern

System.out.println(currencyFormatter.format(amount));

5

esta es la mejor manera de hacer eso.

    public static String formatCurrency(String amount) {
        DecimalFormat formatter = new DecimalFormat("###,###,##0.00");
        return formatter.format(Double.parseDouble(amount));
    }

100 -> "100,00"
100,1 -> "100,10"


5
NumberFormat currency = NumberFormat.getCurrencyInstance();
String myCurrency = currency.format(123.5);
System.out.println(myCurrency);

salida:

$123.50

Si desea cambiar la moneda,

NumberFormat currency = NumberFormat.getCurrencyInstance(Locale.CHINA);
String myCurrency = currency.format(123.5);
System.out.println(myCurrency);

salida:

123.50

4

deberías hacer algo como esto:

public static void main(String[] args) {
    double d1 = 100d;
    double d2 = 100.1d;
    print(d1);
    print(d2);
}

private static void print(double d) {
    String s = null;
    if (Math.round(d) != d) {
        s = String.format("%.2f", d);
    } else {
        s = String.format("%.0f", d);
    }
    System.out.println(s);
}

que imprime:

100

100,10


¿Funcionará Math.round (d)! = D? ¡Con flota a menudo! = Incluso si crees que lo es.
Extraneon

1
de otra manera, si d fuera 100.000000000000001, entonces todavía se imprimiría como 100
Stefan De Boey

4

Sé que esta es una vieja pregunta pero ...

import java.text.*;

public class FormatCurrency
{
    public static void main(String[] args)
    {
        double price = 123.4567;
        DecimalFormat df = new DecimalFormat("#.##");
        System.out.print(df.format(price));
    }
}

3
Esto no funciona, hace 100.1 -> "100.1" por ejemplo - vea stackoverflow.com/questions/5033404/…
davnicwil

4

Puedes hacer algo como esto y pasar el número entero y luego los centavos.

String.format("$%,d.%02d",wholeNum,change);

4

Estoy de acuerdo con @duffymo en que necesitas usar los java.text.NumberFormatmétodos para este tipo de cosas. De hecho, puede hacer todo el formateo de forma nativa sin hacer ninguna comparación de cadenas:

private String formatPrice(final double priceAsDouble) 
{
    NumberFormat formatter = NumberFormat.getCurrencyInstance();
    if (Math.round(priceAsDouble * 100) % 100 == 0) {
        formatter.setMaximumFractionDigits(0);
    }
    return formatter.format(priceAsDouble);
}

Par de bits para señalar:

  • El conjunto Math.round(priceAsDouble * 100) % 100está trabajando en torno a las inexactitudes de los dobles / flotantes. Básicamente, solo verificando si redondeamos al lugar de las centenas (tal vez esto sea un sesgo de EE. UU.) ¿Quedan centavos?
  • El truco para quitar los decimales es el setMaximumFractionDigits()método

Cualquiera que sea su lógica para determinar si los decimales deben truncarse o no, setMaximumFractionDigits()debe usarse.


1
Re su punto acerca de la *100y %100es empujada por Estados Unidos, se puede utilizar Math.pow(10, formatter.getMaximumFractionDigits())en lugar de un no modificable 100de utilizar el número correcto para la configuración regional ...
daiscog

3

Si desea trabajar con monedas, debe usar la clase BigDecimal. El problema es que no hay forma de almacenar algunos números flotantes en la memoria (por ejemplo, puede almacenar 5.3456, pero no 5.3455), lo que puede afectar los cálculos incorrectos.

Hay un buen artículo sobre cómo cooperar con BigDecimal y las monedas:

http://www.javaworld.com/javaworld/jw-06-2001/jw-0601-cents.html


2
Esto es completamente irrelevante para la pregunta que he hecho.
DD.

3

Formato de 1000000,2 a 1000000,20

private static final DecimalFormat DF = new DecimalFormat();

public static String toCurrency(Double d) {
    if (d == null || "".equals(d) || "NaN".equals(d)) {
        return " - ";
    }
    BigDecimal bd = new BigDecimal(d);
    bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
    DecimalFormatSymbols symbols = DF.getDecimalFormatSymbols();
    symbols.setGroupingSeparator(' ');
    String ret = DF.format(bd) + "";
    if (ret.indexOf(",") == -1) {
        ret += ",00";
    }
    if (ret.split(",")[1].length() != 2) {
        ret += "0";
    }
    return ret;
}

2

Esta publicación realmente me ayudó a conseguir finalmente lo que quiero. Así que solo quería contribuir con mi código aquí para ayudar a otros. Aquí está mi código con alguna explicación.

El siguiente código:

double moneyWithDecimals = 5.50;
double moneyNoDecimals = 5.00;
System.out.println(jeroensFormat(moneyWithDecimals));
System.out.println(jeroensFormat(moneyNoDecimals));

Regresará:

5,-
€ 5,50

El método jeroensFormat () real:

public String jeroensFormat(double money)//Wants to receive value of type double
{
        NumberFormat dutchFormat = NumberFormat.getCurrencyInstance();
        money = money;
        String twoDecimals = dutchFormat.format(money); //Format to string
        if(tweeDecimalen.matches(".*[.]...[,]00$")){
            String zeroDecimals = twoDecimals.substring(0, twoDecimals.length() -3);
                return zeroDecimals;
        }
        if(twoDecimals.endsWith(",00")){
            String zeroDecimals = String.format("€ %.0f,-", money);
            return zeroDecimals; //Return with ,00 replaced to ,-
        }
        else{ //If endsWith != ,00 the actual twoDecimals string can be returned
            return twoDecimals;
        }
}

El método displayJeroensFormat que llama al método jeroensFormat ()

    public void displayJeroensFormat()//@parameter double:
    {
        System.out.println(jeroensFormat(10.5)); //Example for two decimals
        System.out.println(jeroensFormat(10.95)); //Example for two decimals
        System.out.println(jeroensFormat(10.00)); //Example for zero decimals
        System.out.println(jeroensFormat(100.000)); //Example for zero decimals
    }

Tendrá la siguiente salida:

10,5010,9510,-
€ 100.000 (In Holland numbers bigger than € 999,- and wit no decimals don't have ,-)

Este código usa su moneda actual. En mi caso, eso es Holanda, por lo que la cadena formateada para mí será diferente a la de alguien en los EE. UU.

  • Holanda: 999.999,99
  • Estados Unidos: 999,999.99

Solo mira los últimos 3 caracteres de esos números. Mi código tiene una declaración if para verificar si los últimos 3 caracteres son iguales a ", 00". Para usar esto en los EE. UU., Es posible que deba cambiarlo a ".00" si aún no funciona.


2

Estaba lo suficientemente loco como para escribir mi propia función:

Esto convertirá el formato entero a moneda (también se puede modificar para decimales):

 String getCurrencyFormat(int v){
        String toReturn = "";
        String s =  String.valueOf(v);
        int length = s.length();
        for(int i = length; i >0 ; --i){
            toReturn += s.charAt(i - 1);
            if((i - length - 1) % 3 == 0 && i != 1) toReturn += ',';
        }
        return "$" + new StringBuilder(toReturn).reverse().toString();
    }

2
  public static String formatPrice(double value) {
        DecimalFormat formatter;
        if (value<=99999)
          formatter = new DecimalFormat("###,###,##0.00");
        else
            formatter = new DecimalFormat("#,##,##,###.00");

        return formatter.format(value);
    }

1

Esto es lo que hice, usando un número entero para representar la cantidad como centavos en su lugar:

public static String format(int moneyInCents) {
    String format;
    Number value;
    if (moneyInCents % 100 == 0) {
        format = "%d";
        value = moneyInCents / 100;
    } else {
        format = "%.2f";
        value = moneyInCents / 100.0;
    }
    return String.format(Locale.US, format, value);
}

El problema NumberFormat.getCurrencyInstance()es que a veces realmente quieres que $ 20 sean $ 20, simplemente se ve mejor que $ 20,00.

Si alguien encuentra una mejor manera de hacer esto, usando NumberFormat, soy todo oídos.


1

Para las personas que desean formatear la moneda, pero no quieren que se base en local, podemos hacer esto:

val numberFormat = NumberFormat.getCurrencyInstance() // Default local currency
val currency = Currency.getInstance("USD")            // This make the format not locale specific 
numberFormat.setCurrency(currency)

...use the formator as you want...
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.