BigDecimal-new 또는 valueOf 사용


101

Double d에서 BigDecimal 객체를 얻는 두 가지 방법을 발견했습니다.

1. new BigDecimal(d)
2. BigDecimal.valueOf(d)

더 나은 접근 방식은 무엇입니까? valueOf가 새 개체를 만들까요?

일반적으로 (BigDecimal뿐만 아니라) 권장되는 것은 무엇입니까-new 또는 valueOf?

감사.


10
일반적으로 valueOf가 선호되지만 ( "인기있는"인스턴스를 재사용하여 새 개체를 만드는 것을 피할 수 있기 때문에) BigDecimals 및 double의 경우 불행히도 두 메서드가 다른 결과를 생성하므로 필요한 것을 선택해야합니다.
Thilo

답변:


163

두 가지 질문이 있습니다. "무엇을 사용해야 BigDecimal합니까?" 및 "일반적으로 무엇을합니까?"

For BigDecimal: 그들은 같은 일하지 않기 때문에 약간 까다 롭습니다 . 전달 된 값 BigDecimal.valueOf(double)표준 String표현 을 사용하여 개체 double를 인스턴스화 BigDecimal합니다. 다른 말로하면, BigDecimal물체 의 가치는 당신이 할 때 보게 될 것 System.out.println(d)입니다.

new BigDecimal(d)그러나을 사용 하면 BigDecimal가능한 한 정확하게double 값 을 나타내려고 합니다 . 이로 인해 일반적으로 원하는 것보다 훨씬 많은 숫자가 저장됩니다. 엄밀히 말하면보다 정확 valueOf()하지만 훨씬 덜 직관적입니다.

JavaDoc에 이에 대한 멋진 설명이 있습니다.

이 생성자의 결과는 다소 예측할 수 없습니다. 하나는 서면으로 가정 할 수 new BigDecimal(0.1)자바가 생성 BigDecimal(1의 규모로, 1의 스케일 없음의 값) 0.1 정확하게 일치되는, 그러나 실제로 0.1000000000000000055511151231257827021181583404541015625 같음. 이는 0.1이 정확히 a double(또는 유한 길이의 이진 분수로) 로 표현 될 수 없기 때문 입니다. 따라서 생성자에 전달되는 값은 외관에도 불구하고 정확히 0.1과 동일하지 않습니다.

일반적으로 결과가 동일한 경우 (예 :의 경우가 BigDecimal아니라 대부분의 다른 경우) valueOf()선호되어야합니다. 공통 값의 캐싱을 수행 할 수 있고 (에서 볼 수 있음 Integer.valueOf()) 캐싱 동작을 변경할 수도 있습니다. 발신자를 변경해야합니다. new것입니다 항상 , 경우에도 필요하지 않습니다 (: 좋은 예 새 값을 인스턴스화 new Boolean(true)대를 Boolean.valueOf(true)).


이것은 또한 내 질문을 설명합니다 : stackoverflow.com/questions/15685705/…
Christian

3
@Joachim, 명확하지 않았습니다. 인가 new BigDecimal()보다 BigDecimal.valueOf()?
ryvantage

5
@ryvantage : 하나가 다른 것보다 엄격하게 더 나은 경우 둘 다 필요하지 않으며 내 대답은 훨씬 짧을 것입니다. 그들은 똑같은 일을하지 않기 때문에 그렇게 순위를 매길 수 없습니다.
Joachim Sauer

2
@JoachimSauer, 알겠습니다. 좀 더 구체적 이었어 야 했어요. new BigDecimal()선호되는시기와 선호되는 시기의 예를 들어 주시겠습니까 BigDecimal.valueOf()?
ryvantage

@ryvantage : new BigDecimal(1.0/30.0);및 의 결과를 비교합니다 BigDecimal.valueOf(1.0/30.0). 어떤 결과가 실제로 숫자 분수 1/30에 더 가까운 지 확인하십시오.
supercat 2014-04-04

48

BigDecimal개체를 사용하여 통화 값을 저장 하는 경우 계산에 이중 값을 포함 하지 않는 것이 좋습니다 .

다른 답변에서 언급했듯이 이중 값으로 알려진 정확도 문제가 있으며 이는 큰 시간을 보내 게 될 것입니다.

그것을지나 치면 질문에 대한 답은 간단합니다. 에 대한 valueOf메서드 가 없으므로 항상 String 값이있는 생성자 메서드를 생성자에 대한 인수로 사용합니다 String.

증거를 원하면 다음을 시도하십시오.

BigDecimal bd1 = new BigDecimal(0.01);
BigDecimal bd2 = new BigDecimal("0.01");
System.out.println("bd1 = " + bd1);
System.out.println("bd2 = " + bd2);

다음과 같은 출력이 표시됩니다.

bd1 = 0.01000000000000000020816681711721685132943093776702880859375
bd2 = 0.01

관련 질문 도 참조하십시오.


5

기본적으로 valueOf (double val)는 다음과 같이합니다.

return new BigDecimal(Double.toString(val));

따라서-> 예, 새 개체가 생성됩니다. :).

일반적으로 코딩 스타일에 따라 다릅니다. 둘 다 동일한 결과이면 valueOf와 "new"를 혼합하지 않습니다.


7
기술적으로는 사실 이지만 차이를 만들 것 입니다. valueOf()직관적 인 행동을하는 반면 new BigDecimal(d), 더 정확한 행동 을합니다 . 둘 다 시도하고 차이점을 확인하십시오.
Joachim Sauer 2011 년

기술적으로 거짓입니다. 'new'always 키워드는 항상 새 객체를 생성하지만 javadoc은 valueOf가 항상 새 객체를 반환하는지 여부를 알려주지 않습니다. 항상 그런 것은 아닙니다. 캐시에 일부 값이 new BigDecimal(1) != new BigDecimal(1)있지만BigDecimal.valueOf(1) == BigDecimal.valueOf(1)
aalku

1
@user는 : 이후 네,하지만 BigDecimal불변 그것은 원시 래퍼 (것과 같은 방식으로 취급되어야한다 Integer, Byte...)와이 String객체 ID는 : 취급 문제가되지해야합니다 귀하의 코드 만 값은 중요해야합니다.
Joachim Sauer 2011 년

@Joachim 맞지만 그 내부 캐시에는 이유가 있습니다. 필요하지 않은 동일한 BigDecimal 인스턴스가 너무 많으면 좋은 것이 아닙니다. 그리고 나는 Dr에게 대답했습니다. 그는 "새로운 개체가 생성 될 것입니다"라고 말했습니다
aalku

3
@user : 예, 이것이 일반적 으로 선호 valueOf()되어야한다고 말한 이유 입니다. 그러나 캐싱을 수행하지 않습니다 (아마도 그럴 가치가 없을 것입니다). BigDecimal.valueOf(double)
Joachim Sauer 2011 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.