utilizar tutorial interfaz gui graficos grafica español componentes como java types currency

tutorial - jframe en java



¿Cuál es el mejor tipo de datos para usar con dinero en la aplicación Java? (11)

¿Cuál es el mejor tipo de datos para usar con dinero en la aplicación Java?


BigDecimal es el mejor tipo de datos para usar en moneda.

Hay muchos contenedores para moneda, pero todos usan BigDecimal como el tipo de datos subyacente. No se equivocará con BigDecimal, probablemente utilizando el redondeo BigDecimal.ROUND_HALF_EVEN.


Debe usar BigDecimal para representar valores monetarios. Le permite usar una variedad de modos de redondeo , y en aplicaciones financieras, el modo de redondeo es a menudo un requisito difícil que incluso puede ser obligatorio por ley.


He hecho un microbenchmark (JMH) para comparar Moneta (implementación de moneda java JSR 354) contra BigDecimal en términos de rendimiento.

Sorprendentemente, el rendimiento de BigDecimal parece ser mejor que el de Moneta. He usado la siguiente configuración moneta:

org.javamoney.moneta.Money.defaults.precision = 19 org.javamoney.moneta.Money.defaults.roundingMode = HALF_UP

package com.despegar.bookedia.money; import org.javamoney.moneta.FastMoney; import org.javamoney.moneta.Money; import org.openjdk.jmh.annotations.*; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; import java.util.concurrent.TimeUnit; @Measurement(batchSize = 5000, iterations = 10, time = 2, timeUnit = TimeUnit.SECONDS) @Warmup(iterations = 2) @Threads(value = 1) @Fork(value = 1) @State(Scope.Benchmark) @BenchmarkMode(Mode.Throughput) public class BigDecimalBenchmark { private static final Money MONEY_BASE = Money.of(1234567.3444, "EUR"); private static final Money MONEY_SUBSTRACT = Money.of(232323, "EUR"); private static final FastMoney FAST_MONEY_SUBSTRACT = FastMoney.of(232323, "EUR"); private static final FastMoney FAST_MONEY_BASE = FastMoney.of(1234567.3444, "EUR"); MathContext mc = new MathContext(10, RoundingMode.HALF_UP); @Benchmark public void bigdecimal_string() { new BigDecimal("1234567.3444").subtract(new BigDecimal("232323")).multiply(new BigDecimal("3.4"), mc).divide(new BigDecimal("5.456"), mc); } @Benchmark public void bigdecimal_valueOf() { BigDecimal.valueOf(12345673444L, 4).subtract(BigDecimal.valueOf(232323L)).multiply(BigDecimal.valueOf(34, 1), mc).divide(BigDecimal.valueOf(5456, 3), mc); } @Benchmark public void fastmoney() { FastMoney.of(1234567.3444, "EUR").subtract(FastMoney.of(232323, "EUR")).multiply(3.4).divide(5.456); } @Benchmark public void money() { Money.of(1234567.3444, "EUR").subtract(Money.of(232323, "EUR")).multiply(3.4).divide(5.456); } @Benchmark public void money_static(){ MONEY_BASE.subtract(MONEY_SUBSTRACT).multiply(3.4).divide(5.456); } @Benchmark public void fastmoney_static() { FAST_MONEY_BASE.subtract(FAST_MONEY_SUBSTRACT).multiply(3.4).divide(5.456); } }

Resultando en

Benchmark Mode Cnt Score Error Units BigDecimalBenchmark.bigdecimal_string thrpt 10 479.465 ± 26.821 ops/s BigDecimalBenchmark.bigdecimal_valueOf thrpt 10 1066.754 ± 40.997 ops/s BigDecimalBenchmark.fastmoney thrpt 10 83.917 ± 4.612 ops/s BigDecimalBenchmark.fastmoney_static thrpt 10 504.676 ± 21.642 ops/s BigDecimalBenchmark.money thrpt 10 59.897 ± 3.061 ops/s BigDecimalBenchmark.money_static thrpt 10 184.767 ± 7.017 ops/s

Por favor, siéntete libre de corregirme si me falta algo


Me gusta usar Tiny Types que incluiría un doble, BigDecimal o int, como lo sugirieron las respuestas anteriores. (Utilizaría un doble a menos que surjan problemas de precisión).

Un Tiny Type te da seguridad de tipo para que no confundas un doble de dinero con otros dobles.


Para el caso simple (una moneda) es suficiente Integer / Long . Mantenga el dinero en centavos (...) o en centésimas / milésimas de centavos (cualquier precisión que necesite con el divisor fijo)


Puede usar Money and Currency API (JSR 354) . Se espera que esta API forme parte de Java 9. Puede usar esta API en Java 7 y Java 8, siempre que agregue dependencias apropiadas a su proyecto.

Para Java 8, agregue la siguiente implementación de referencia como una dependencia de su pom.xml :

<dependency> <groupId>org.javamoney</groupId> <artifactId>moneta</artifactId> <version>1.0</version> </dependency>

Esta dependencia agregará transitoriamente javax.money:money-api como una dependencia.

A continuación, puede usar la API:

package com.example.money; import static org.junit.Assert.assertThat; import static org.hamcrest.CoreMatchers.is; import java.util.Locale; import javax.money.Monetary; import javax.money.MonetaryAmount; import javax.money.MonetaryRounding; import javax.money.format.MonetaryAmountFormat; import javax.money.format.MonetaryFormats; import org.junit.Test; public class MoneyTest { @Test public void testMoneyApi() { MonetaryAmount eurAmount1 = Monetary.getDefaultAmountFactory().setNumber(1.1111).setCurrency("EUR").create(); MonetaryAmount eurAmount2 = Monetary.getDefaultAmountFactory().setNumber(1.1141).setCurrency("EUR").create(); MonetaryAmount eurAmount3 = eurAmount1.add(eurAmount2); assertThat(eurAmount3.toString(), is("EUR 2.2252")); MonetaryRounding defaultRounding = Monetary.getDefaultRounding(); MonetaryAmount eurAmount4 = eurAmount3.with(defaultRounding); assertThat(eurAmount4.toString(), is("EUR 2.23")); MonetaryAmountFormat germanFormat = MonetaryFormats.getAmountFormat(Locale.GERMAN); assertThat(germanFormat.format(eurAmount4), is("EUR 2,23") ); } }


Un tipo integral que representa el valor más pequeño posible. En otras palabras, su programa debería pensar en centavos, no en dólares / euros.

Esto no debería impedir que la GUI lo traduzca de nuevo a dólares / euros.


Yo usaría Joda Money

Todavía está en la versión 0.6 pero parece muy prometedor



JSR 354: API de dinero y divisas

JSR 354 proporciona una API para representar, transportar y realizar cálculos integrales con dinero y moneda. Puedes descargarlo desde este enlace:

JSR 354: Descargar la API de dinero y divisas

La especificación consiste en las siguientes cosas:

  1. Una API para manejar, por ejemplo, montos monetarios y monedas
  2. API para admitir implementaciones intercambiables
  3. Fábricas para crear instancias de las clases de implementación
  4. Funcionalidad para cálculos, conversión y formateo de importes monetarios
  5. API de Java para trabajar con dinero y divisas, que se planea incluir en Java 9.
  6. Todas las clases de especificación e interfaces se encuentran en el paquete javax.money. *.

Ejemplos de muestra de JSR 354: Money and Currency API:

Un ejemplo de cómo crear MonetaryAmount e imprimirlo en la consola es similar a este ::

MonetaryAmountFactory<?> amountFactory = Monetary.getDefaultAmountFactory(); MonetaryAmount monetaryAmount = amountFactory.setCurrency(Monetary.getCurrency("EUR")).setNumber(12345.67).create(); MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(Locale.getDefault()); System.out.println(format.format(monetaryAmount));

Cuando se utiliza la API de implementación de referencia, el código necesario es mucho más simple:

MonetaryAmount monetaryAmount = Money.of(12345.67, "EUR"); MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(Locale.getDefault()); System.out.println(format.format(monetaryAmount));

La API también admite cálculos con MonetaryAmounts:

MonetaryAmount monetaryAmount = Money.of(12345.67, "EUR"); MonetaryAmount otherMonetaryAmount = monetaryAmount.divide(2).add(Money.of(5, "EUR"));

CurrencyUnit y MonetaryAmount

// getting CurrencyUnits by locale CurrencyUnit yen = MonetaryCurrencies.getCurrency(Locale.JAPAN); CurrencyUnit canadianDollar = MonetaryCurrencies.getCurrency(Locale.CANADA);

MonetaryAmount tiene varios métodos que permiten acceder a la moneda asignada, la cantidad numérica, su precisión y más:

MonetaryAmount monetaryAmount = Money.of(123.45, euro); CurrencyUnit currency = monetaryAmount.getCurrency(); NumberValue numberValue = monetaryAmount.getNumber(); int intValue = numberValue.intValue(); // 123 double doubleValue = numberValue.doubleValue(); // 123.45 long fractionDenominator = numberValue.getAmountFractionDenominator(); // 100 long fractionNumerator = numberValue.getAmountFractionNumerator(); // 45 int precision = numberValue.getPrecision(); // 5 // NumberValue extends java.lang.Number. // So we assign numberValue to a variable of type Number Number number = numberValue;

MonetaryAmounts se puede redondear utilizando un operador de redondeo:

CurrencyUnit usd = MonetaryCurrencies.getCurrency("USD"); MonetaryAmount dollars = Money.of(12.34567, usd); MonetaryOperator roundingOperator = MonetaryRoundings.getRounding(usd); MonetaryAmount roundedDollars = dollars.with(roundingOperator); // USD 12.35

Al trabajar con colecciones de MonetaryAmounts, hay algunos buenos métodos de utilidad para filtrar, clasificar y agrupar disponibles.

List<MonetaryAmount> amounts = new ArrayList<>(); amounts.add(Money.of(2, "EUR")); amounts.add(Money.of(42, "USD")); amounts.add(Money.of(7, "USD")); amounts.add(Money.of(13.37, "JPY")); amounts.add(Money.of(18, "USD"));

Operaciones MonetaryAmount personalizadas

// A monetary operator that returns 10% of the input MonetaryAmount // Implemented using Java 8 Lambdas MonetaryOperator tenPercentOperator = (MonetaryAmount amount) -> { BigDecimal baseAmount = amount.getNumber().numberValue(BigDecimal.class); BigDecimal tenPercent = baseAmount.multiply(new BigDecimal("0.1")); return Money.of(tenPercent, amount.getCurrency()); }; MonetaryAmount dollars = Money.of(12.34567, "USD"); // apply tenPercentOperator to MonetaryAmount MonetaryAmount tenPercentDollars = dollars.with(tenPercentOperator); // USD 1.234567

Recursos:

Manejo de dinero y monedas en Java con JSR 354

Examinando la API de dinero y divisas de Java 9 (JSR 354)

Ver también: JSR 354 - Moneda y dinero


Java tiene una clase de Currency que representa los códigos de moneda ISO 4217. BigDecimal es el mejor tipo para representar valores decimales monetarios.

Joda Money ha proporcionado una biblioteca para representar dinero.