Programing

Java에서 돈으로 사용할 데이터 유형을 선택하십시오.

c10106 2022. 4. 23. 10:07
반응형

Java에서 돈으로 사용할 데이터 유형을 선택하십시오.

자바에서는 어떤 데이터 유형을 사용하여 돈을 지불해야 하는가?

자바에는 ISO 4217 통화 코드를 나타내는 클래스가 있다. BigDecimal통화 십진수 값을 나타내는 데 가장 좋은 유형이다.

Joda Money는 돈을 대표할 수 있는 도서관을 제공했다.

통화통화 API(JSR 354)를 사용할 수 있다.프로젝트에 적절한 종속성을 추가하면 이 API를 에서 사용할 수 있다.

, 다음 참조 을 Java 8의 경우다다다다다다을을을을을을을을을을 to to to to to to에 pom.xml:

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

이 의존성은 전적으로 추가될 것이다.javax.money:money-api의존으로

그런 다음 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") );
    }
}

가능한 가장 작은 값을 나타내는 정수.다시 말해, 당신의 프로그램은 달러/유로화가 아닌 센트로 생각해야 한다.

이것은 당신이 그것을 달러/유로화로 다시 번역하게 하는 것을 막지 말아야 한다.

BigDecimal을 사용할 수 있으며, Float 또는 Double을 사용하지 않는 이유에 대한 좋은 설명은 여기에서 확인할 수 있다.통화를 나타내기 위해 이중 또는 부동산을 사용하는 것은 어떠한가?

JSR 354: 통화 및 통화 API

JSR 354는 화폐와 화폐로 포괄적 계산을 표현, 운반 및 수행하기 위한 API를 제공한다.다음 링크에서 다운로드 가능:

JSR 354: 통화 및 통화 API 다운로드

명세서는 다음과 같은 것으로 구성된다.

  1. 통화량 및 통화 등의 처리를 위한 API
  2. 상호 호환 가능한 구현을 지원하는 API
  3. 구현 클래스의 인스턴스를 만드는 공장
  4. 화폐 금액의 계산, 환산 및 서식을 위한 기능
  5. 자바 9에 포함될 예정인 머니·통화와의 협력을 위한 자바 API.
  6. 모든 사양 등급과 인터페이스는 자바스.머니에 위치한다.* 패키지.

JSR 354의 예: 통화 및 통화 API:

Monthmount를 생성하고 이를 콘솔에 인쇄하는 예는 다음과 같다.

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));

참조 구현 API를 사용할 때 필요한 코드는 훨씬 간단하다.

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

또한 API는 Monthmounts를 사용한 계산을 지원한다.

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

통화단위 및 통화금액

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

통화량에는 할당된 통화, 숫자 금액, 정확도 등을 액세스할 수 있는 다양한 방법이 있다.

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;

통화량은 반올림 연산자를 사용하여 반올림할 수 있다.

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

Monthmounts 모음으로 작업할 때 필터링, 정렬 및 그룹화를 위한 몇 가지 유용한 유틸리티 방법을 사용할 수 있다.

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"));

사용자 지정 통화 금액 작업

// 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

리소스:

JSR 354로 자바에서 통화 및 통화 처리

Java 9 Money and Currency API(JSR 354) 조사

참고 항목: JSR 354 - 통화통화

당신은 통화 가치를 나타내기 위해 BigDecimal을 사용해야 한다.다양한 라운딩 모드를 사용할 수 있게 해주며, 재무적 응용에서 라운딩 모드는 법률에 의해 강제될 수 있는 어려운 요구사항인 경우가 많다.

성과 면에서 모네타(자바 통화 JSR 354 이행)와 빅데히말(BigDecimal)을 비교하는 마이크로벤치마크(JMH)를 해봤다.

놀랍게도 빅데시멀의 활약이 모네타의 활약보다 나은 것 같다.나는 다음과 같은 모네타 구성을 사용해왔다.

org.javamoney.moneta.Money.defaults.precision=19 org.javamoney.moneta.Money.defaults.roundingMode=하프_업

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);
    }
}

결과

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

내가 놓친 게 있으면 얼마든지 고쳐줘.

나는 조다 머니를 사용할 것이다.

아직 버전 0.6이지만 매우 유망해 보인다.

간단한 경우(통화 한 개)면 충분하다.int/long. 센트 (...) 또는 100/1000 센트 (고정 분할기로 필요한 정밀도)로 돈을 보관한다.

BigDecimal은 통화에 사용하기 가장 좋은 데이터 유형이다.

통화용 컨테이너가 아주 많지만, 모두 BigDecimal을 기본 데이터 유형으로 사용한다.BigDecimal은 틀리지 않을거야 아마 BigDecimal을 사용할거야라운드_하프_이븐 라운딩.

나는 이전 답변에서 제시했던 것처럼 더블, 빅데히말, int를 포장하는 타이니 타입을 사용하는 것을 좋아한다.(정밀 문제가 커지지 않는 한 나는 두 배의 정밀도를 사용할 것이다.

타이니 타입은 당신에게 타입의 안전성을 제공하므로 당신은 더블 머니를 다른 더블 머신과 혼동하지 않는다.

참조URL: https://stackoverflow.com/questions/8148684/what-data-type-to-use-for-money-in-java

반응형