자바로 화폐 가치 표현하기 [닫힌]


94

BigDecimal이 Java에서 화폐 가치를 표현하는 데 권장되는 모범 사례라는 것을 이해합니다. 당신은 무엇을 사용합니까? 대신 사용하고 싶은 더 나은 라이브러리가 있습니까?


4
에서 살펴 JSR 354
yegor256

1
복사하고 확장 할 수있는 Currency 클래스는 다음과 같습니다. java-articles.info/articles/?p=254
Gilbert Le Blanc

답변:


81

BigDecimal모든 방법. 나는 어떤 사람들은 자신의 창조 들었어요 Cash또는 Money통화와 현금 가치를 캡슐화 클래스를,하지만 피부 아래 여전히입니다 BigDecimal아마로, BigDecimal.ROUND_HALF_EVEN반올림.

편집 : Don이 그의 대답 에서 언급 했듯이 timeandmoney 와 같은 오픈 소스 프로젝트가 있으며 개발자가 바퀴를 재발 명하지 않도록 노력한 것에 대해 박수를 보내지 만 사용할 사전 알파 라이브러리에 대한 확신이 충분하지 않습니다. 프로덕션 환경에서. 게다가, 후드 아래를 파헤 치면 그들이 사용하는 BigDecimal것을수 있습니다 .


4
+1. 통화를 소비하는 컨테이너 클래스도 추가하기로 결정했습니다. 이것은 테이블에서 화폐 가치를 렌더링 할 때 유용합니다.
Daniel Hiller

1
예, 그것은 매우 일반적인 접근 방식이며 많은 의미가 있습니다. 이에 대한 한 가지주의 사항은 일본 엔화를 처리해야 할 때입니다. 일본 엔화는 센트와 같은 작은 화폐 단위가 없기 때문에 자체 반올림 규칙이 필요합니다.
ninesided

3
@ninesided는 자신의 롤링이 왜 나쁜 대답인지에 대한 좋은 예를 제공합니다. "그런데 $ CURRENCY_X에서는 작동하지 않습니다." 이는 다른 많은 통화에서도 작동하지 않는다는 좋은 신호입니다.
James Moore

1
@JamesMoore 나는 "자신의 롤링"이 나쁜 접근법이라는 것에 동의하지 않는다. 당신은 당신이 선택한 접근법의 가능한 한계를 알고 있어야한다. 그래서 내가 그것을 언급하는 이유이다. 통화마다 다른 반올림 규칙을 구현하는 것은 사소한 일이지만 시스템이 USD 또는 EUR로만 처리해야하는 경우에는 과도하게 엔지니어링 할 필요가 없습니다.
ninesided 2011

1
한 번 봐 가지고 stackoverflow.com/questions/5134237/... 의 BigDecimal이 문제가 왜 하나의 이유입니다. 전 지구 적 회계는 특별한 경우의 늪일 뿐이며 BigDecimal의 깔개 아래에서 모든 것을 훑어 보려는 시도는 작동하지 않습니다.
James Moore



8

앞서 살펴본 편리한 도서관은 Joda-Money 도서관입니다. 구현 중 하나는 실제로 BigDecimal을 기반으로합니다. 통화 에 대한 ISO-4217 사양을 기반으로 하며 사용자 지정 통화 목록 (CVS를 통해로드 됨)을 지원할 수 있습니다.

이 라이브러리에는 수정이 필요한 경우 신속하게 통과 할 수있는 적은 수의 파일이 있습니다. Joda-Money는 Apache 2.0 라이선스에 따라 게시됩니다.


7

달러와 센트 만 사용하는 경우에는 long (소수점 2 자리 오프셋)을 사용합니다. 더 자세한 정보가 필요하면 큰 십진수를 사용하는 것이 좋습니다.

어느 쪽이든, 올바른 형식을 사용하는 .toString ()을 가지도록 클래스를 확장하고 다른 메서드를 넣을 수있는 장소로 사용할 것입니다 (긴 소수의 경우 곱셈과 나눗셈이 잘못 될 것입니다). 조정되지 않음)

또한 자신의 클래스와 인터페이스를 정의하는 경우 원하는대로 구현을 대체 할 수 있습니다.


2
지금이 아니라면 몇 년 안에 미국 연방 부채를 센트 단위로 유지하기에는 너무 긴 것이 너무 짧을 수 있습니다.
Ingo

3
저도 동의합니다. (또는 엔화로 돈을 추적하는 경우) BigDecimal을 사용해야하지만 그럼에도 불구하고 컨테이너 클래스를 사용하는 것을 진지하게 고려할 것입니다. 대부분의 프로그래밍 복잡성은 컬렉션과 내장형을 중심으로 작고 단순한 클래스를 정의하지 않는 사람들에서 비롯된 것이라고 생각합니다.
Bill K

3

BigDecimal 또는 다른 고정 소수점 표현은 일반적으로 돈에 필요한 것입니다.

부동 소수점 ( Double, Float) 표현 및 계산이 정확하지 않아 잘못된 결과가 발생합니다.


7
엄밀히 말하면 BigDecimal도 정확하지 않습니다. 그것은 우리가 일상 생활에서 사용하는 소수 반올림과 더 잘 일치하며 반올림 모드를 지정할 수 있습니다.
Michael Borgwardt

1
@Michael Borgwardt BigDecimal은 명시 적 스케일이 지정된다는 점에서 IEEE FP와 다릅니다. 모든 작업이 정확하지는 않지만 이는 일련의 작업 및 동작이 항상 정확하고 규모가 일정 하도록 보장하는 반면 IEEE FP의 규모는 값에 따라 감소합니다.

1
그게 돈과 무슨 관련이 있습니까? 전 세계의 회계 조직은 일반적으로 자신의 통화로 수학을 수행하는 방법에 대한 매우 구체적인 요구 사항을 가지고 있습니다. BigDecimal은 이러한 표준 각각과 정확히 일치합니까? 내년 기준이 변경되면 그렇게할까요? 그리고 BigDecimal은 통화에 대한 유용한 반올림 규칙을 지정하는데도 근접하지 않습니다.
James Moore 2011

2

시간과 돈을 다룰 때 너무 조심해야합니다.

당신이 돈으로 일할 때, 나는 모두가 절대로 플로트 나 더블을 사용하지 말아야한다는 것을 알아야합니다.

하지만 BigDecimal에 대해 잘 모르겠습니다.

대부분의 경우 int 또는 long으로 센트를 추적하면 괜찮습니다. 이런 식으로 소수점 자리를 처리하지 않습니다.

인쇄 할 때만 달러를 표시합니다. 항상 정수를 사용하여 내부 센트로 작업하십시오. Math.abs ()를 분할하거나 사용해야하는 경우 까다로울 수 있습니다.

그러나 당신은 반 센트, 심지어는 100 분의 1 센트까지 신경 쓸 수 있습니다. 이 작업을 수행하는 좋은 방법이 무엇인지 모르겠습니다. 천분의 일을 처리하고 long을 사용해야 할 수도 있습니다. 또는 BigDecimal을 사용해야 할 수도 있습니다.

나는 이것에 대해 더 많은 것을 읽고 싶지만 돈을 표현하기 위해 float 또는 double을 사용하는 것에 대해 이야기하기 시작하는 모든 사람들을 무시합니다. 그들은 단지 문제를 요구하고 있습니다.

제 조언이 완전하지 않다고 생각하니 더 많이 넣어주세요. 당신은 위험한 유형을 다루고 있습니다!


2
BigDecimal을 사용하려면 왜 "강제"를 받아야합니까? 무엇에 대해 잘 모르시겠습니까? 반올림 모드를 명시 적으로 지정할 수 있으므로 센트로 작업하는 것보다 분명히 우수합니다.
Michael Borgwardt

1
@MichaelBorgwardt : 예, 통화에 필요한 반올림 모드의 작은 하위 집합을 지정할 수 있습니다. 그래서? (힌트 : 반올림 통화는 일반적으로 국가 회계 기관에서 결정합니다. 이상한 특수한 경우에 완벽하게 기뻐합니다. BigDecimal 반올림이 완전히 완료되는 여러 재미있는 이유 중 하나에 대해서는 stackoverflow.com/questions/5134237/… 을 참조하십시오. 여기에서 쓸모가 없습니다.)
James Moore

@James : 정확히 얼마나 "쓸모없는"것입니까? BigDecimal을 사용하면 다른 것보다 특수한 경우를 구현하는 것이 어떻게 더 어려울까요?
Michael Borgwardt 2011

1
좋아요, 완전히 쓸모없는 것은 너무 강합니다. 통화를 추상화하는 복잡한 클래스에서 BigDecimal의 반올림 규칙은 일부 특정 인스턴스에서 통화 반올림이 발생하는 방식의 하위 집합을 만드는 데 유용 할 수 있습니다. 그러나 일반적인 경우는 통화에 대한 반올림 규칙에는 시간이 지남에 따라 변경 될 수있는 메커니즘이 필요하다는 것입니다 (인간 회계 기관이 규칙을 구성하고 자유롭게 변경할 수 있기 때문에). 문제는 유로 (또는 다음 달에 유로를 대체하는 것이 무엇이든 ...) 나 2011 년의 달러에 관한 것이 아니라 통화에 관한 것이기 때문에 많은 복잡한 복잡성을 처리해야합니다.
James Moore 2011

2

Money 클래스를 만드는 것이 좋습니다. 아래에 BigDecimal (또는 심지어 int) 사용. 그런 다음 Currency 클래스를 사용하여 반올림 규칙을 정의합니다.

불행히도 운영자가 Java를 오버로드하지 않으면 이러한 기본 유형을 만드는 것이 매우 불쾌합니다.


2

더 나은 라이브러리 인 timeandmoney가 있습니다. IMO는이 두 가지 개념을 표현하기 위해 JDK에서 제공하는 라이브러리보다 훨씬 우수합니다.


3
이 답변은 3 년 전에 게시되었습니다. 오늘날 timeandmoney 프로젝트는 해당 링크에 따라 여전히 사전 알파입니다.
James Moore

1
@JamesMoore 좋은 전화입니다. 대답은 이제 7 년이되었고 프로젝트는 여전히 안정적이지 않습니다.
Navin 2015 년

1

확실히 BigDecimal이 아닙니다. 반올림 및 표시에 대한 특별한 규칙이 너무 많아 걱정해야합니다.

Martin Fowler 는 통화 금액을 나타내는 전용 Money 클래스 구현을 권장하며 이는 통화 변환 규칙도 구현합니다.


6
그리고 그의 Money 클래스의 기본 데이터 유형? BigDecimal.
ninesided

1
그건 사실이 아니야. Money 클래스에서 Integer를 사용할 수 있습니다. 마틴이하는 일입니다. 나는 이것을 여러 번했다.
egervari 2011

그러나 권장 사항은 정확합니다. 돈과 관련된 계산은 시간이 지남에 따라 변하는 특별한 경우의 방대한 늪입니다. BigDecimal은 솔루션의 작은 부분으로 유용 할 수 있지만 확실히 일반적이지 않습니다.
James Moore

1

여기에 BigDecimal에 대한 매우 흥미로운 기사가 ​​있습니다. 왜 때때로 double 대신 사용되는지에 대한 설명이 있습니다. BigDecimal 튜토리얼 .


0

궁극적으로 통화 값을 표시 할 때 DecimalFormat 클래스를 사용할 수 있습니다. 현지화 지원을 제공하며 매우 확장 가능합니다.


0

위에서 언급 한 통화가있는 Money 클래스에 BigDecimal을 캡슐화합니다. 중요한 것은 특히 다른 통화로 작업하는 경우 극도의 단위 테스트를 수행한다는 것입니다. 또한 다음과 같이 테스트를 작성할 수 있도록 문자열 또는 동일한 작업을 수행하는 팩토리 메소드를 사용하는 편리한 생성자를 추가하는 것이 좋습니다.

   assertEquals(Money.create("100.0 USD").add("10 GBP"),Money.create("116 USD"));

0

항상 제약과 세부 사항이 관련되어 있습니다. 다음 기사에 설명 된 미묘한 문제를 이해할 수있는 충분한 경험이없는 사람은 실제 재무 데이터를 다루기 전에 진지하게 재고해야합니다.

http://lemnik.wordpress.com/2011/03/25/bigdecimal-and-your-money

BigDecimal은 유일한 올바른 표현이나 퍼즐의 유일한 조각이 아닙니다. 특정 조건이 주어지면 정수로 저장된 센트로 뒷받침되는 Money 클래스를 사용하는 것으로 충분할 수 있으며 BigDecimal보다 훨씬 빠릅니다. 예, 이는 달러를 통화로 사용하고 금액을 제한한다는 것을 의미하지만 이러한 제약은 많은 사용 사례에서 완벽하게 허용되며 모든 통화에는 어쨌든 반올림 및 하위 단위에 대한 특수 사례가 있으므로 "보편적 인"솔루션이 없습니다.


1
이것은 실제 답변이 아닌 다른 게시물에 대한 댓글 인 것 같습니다. 그것은 또한 지나치게 vitriolic입니다. 앞으로 더 예의 바르게 행동하십시오.
Slater Victoroff 2013
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.