2012-02-28 5 views
32

위도/경도에 BigDecimal을 사용해야하는 XSD이 있습니다. 나는 현재 double/lon을 double 형으로 가지고 BigDecimal로 변환하지만 약 12 ​​개 정도의 정밀도를 사용해야합니다. 나는 그것을 설정하는 방법을 알아낼 수 없었다. 아무도 이것으로 나를 도울 수 있습니까?BigDecimal의 특정 정밀도 설정

+0

당신이 생성자 MathContext를주는 시도? – bdares

+1

올바르게 보았다면 부동 소수점 정밀도가 아니라 소수점 자리를 말하는 것입니다. 적어도 받아 들여지는 대답은 정밀도 12 자리가 아닌 소수 12 자리가됩니다. – vbence

답변

60

setScale()과 같이 사용할 수 있습니다.

double d = ... 
BigDecimal db = new BigDecimal(d).setScale(12, BigDecimal.ROUND_HALF_UP); 
+1

Duh. 내가 가진 오류를 되돌아 보면, 반올림이 필요하다고했다. 나는 끝냈다 .setScale (12). 일단 내가 그것이 작동 확인, 나는 대답으로 만들거야. 감사. – Jason

+0

왜 캐스팅과 같은 기본 반올림 메서드를 사용하지 않는지 모르겠지만 ROUND_HALF_UP 만 사용했습니다. 그것은 오히려 현학적입니다. ;) –

+1

+1이 오늘 내 자동화에 도움이되었습니다. – Brian

27

질문의 제목은 정밀도에 대해 묻습니다. BigDecimal은 배율과 정밀도를 구분합니다. Scale은 소수 자릿수입니다. 정밀도는 유효 숫자라고도하는 significant figures의 수로 생각할 수 있습니다.

Clojure의 몇 가지 예입니다.

(.scale  0.00123M) ; 5 
(.precision 0.00123M) ; 3 

(Clojure의에서 M는 BigDecimal를 당신이 좋아하는 경우에 당신은 자바에 Clojure를 번역 할 수 있습니다. 문자 지정,하지만 난 그것을 자바보다 더 컴팩트하게 찾을 수 있습니다!)

, 다음 작업을 쉽게 할 수 있습니다 규모 증가 :

(.setScale 0.00123M 7) ; 0.0M 

을하지만 당신은 할 수 없습니다 감소 동일한 방법으로 규모 :

3,516,

(.setScale 0.00123M 3) ; ArithmeticException Rounding necessary 
당신은 너무 반올림 모드를 통과해야합니다 :

(.setScale 0.00123M 3 BigDecimal/ROUND_HALF_EVEN) ; 
; Note: BigDecimal would prefer that you use the MathContext rounding 
; constants, but I don't have them at my fingertips right now. 

그래서, 그 규모를 쉽게 변경할 수 있습니다. 그러나 정밀도는 어떻습니까? 희망만큼 쉬운 것은 아닙니다!

그것은 정밀도감소에 쉽게 :

(.round 3.14159M (java.math.MathContext. 3)) ; 3.14M 

그러나이 방법 증가 정밀도 명확하지 않다 다음 회의에 대한

(.round 3.14159M (java.math.MathContext. 7)) ; 3.14159M (unexpected) 

,이 하지입니다 후미 0이 표시되지 않습니다.

(.precision (.round 3.14159M (java.math.MathContext. 7))) ; 6 
; (same as above, still unexpected) 

FWIW는 Clojure의는 후행 0에주의하고 그들을 표시합니다 :

궤도에
4.0000M ; 4.0000M 
(.precision 4.0000M) ; 5 

... 당신은 BigDecimal 생성자를 사용하여 시도 할 수 있지만,보다 높은 정밀도를 설정하지 않습니다 지정한 자릿수 :

(BigDecimal. "3" (java.math.MathContext. 5)) ; 3M 
(BigDecimal. "3.1" (java.math.MathContext. 5)) ; 3.1M 

따라서 정확도를 빠르게 변경할 수는 없습니다. 나는이 질문을 쓰는 동안 그리고 내가 일하고있는 프로젝트와 함께 이것을 싸우는 데 시간을 보냈다. 나는 이것을 기껏해야 CRAZYTOWN API와 최악의 버그라고 생각한다. 사람들. 진심으로?당신은 정밀도를 변경하려는 경우

그래서, 최고의 내가 다음 단계를 수행해야합니다, 말할 수 :

  1. 조회 현재 정밀도를.
  2. 현재 눈금을 찾습니다.
  3. 스케일 변경을 계산하십시오.
  4. 는 Clojure의 코드로, 새로운 규모

이 단계를 설정합니다

내가 아는
(def x 0.000691M) ; the input number 
(def p' 1) ; desired precision 
(def s' (+ (.scale x) p' (- (.precision x)))) ; desired new scale 
(.setScale x s' BigDecimal/ROUND_HALF_EVEN) 
; 0.0007M 

, 이것은 단지 정밀도를 변경하려면 많은 단계입니다!

왜 BigDecimal은 이미 이것을 제공하지 않습니까? 내가 간과 했니?

+0

'BigDecimal.round (새로운 MathContext (정밀도, RoundingModel.ROUND_HALF_EVEN))'은 어떨까요? –

+1

@ PaŭloEbermann 당신은 묻고 있습니까? 너 해봤 어? 내 대답을 통해 실행 한 사례에 대한 자세한 결과 공유 그렇다면 별도의 답변이 필요하다고 생각합니다. –

+1

나 같은 사람이고 Clojure에 대해 조금도 알지 못한다면, 여기에있는 해결책은'x.setScale (x.scale() + p - x.precision(), RoundingMode.HALF_UP)'' x'는 반올림하려는 'BigDecimal'이고,'p'는 유지하고자하는 유효 숫자의 수입니다. 그것은 나를 위해 일하고 있지만 내가 틀렸다면 나에게 정정하십시오! – Nateowami

3
BigDecimal decPrec = (BigDecimal)yo.get("Avg"); 
decPrec = decPrec.setScale(5, RoundingMode.CEILING); 
    String value= String.valueOf(decPrec); 

이렇게하면 BigDecimal의 특정 정밀도를 설정할 수 있습니다.

여기 decPrec의 값이 1.5726903423607562595809913132345426이 코드를 시도 1.57267

0

로 반올림 했다 ...

Integer perc = 5; 
    BigDecimal spread = BigDecimal.ZERO; 
    BigDecimal perc = spread.setScale(perc,BigDecimal.ROUND_HALF_UP); 
    System.out.println(perc); 

결과 : 0.00000