2012-09-28 1 views
1

내가 자바 double 값을 반올림하는 데 사용되는 다음과 같은 기능이 있습니다 :자바의 BigDecimal 반올림 오류

double d = 7.3149999999999995; 
int decimalPlace = 2 

하지만, :,이 함수는이 값을 입력으로

public static double round(double d, int decimalPlace) { 

    BigDecimal bd = new BigDecimal(Double.toString(d)); 
    bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP); 
    return bd.doubleValue(); 
} 

수신 함수가 반환하면 반환되는 값은 7.32가 아니라 7.31입니다. 문서를 검색하여 bd.SetScale이 해당 동작을 사용하지만 성공하지 못하는 이유를 확인했습니다.

아무도 내가 이런 일이 일어나는 이유를 설명 할 수 있습니까? 감사합니다.

+0

대신 '7.314999995'를 주면 어떻게됩니까?어쩌면'5'가 사라집니다. – Claudiu

+1

왜 그렇게 놀라운가요? 정확히 7.31에서 7.32 사이가 아니기 때문에 왜 7.32로 반올림됩니까? –

+0

무엇이 7.3159999999999 ...? –

답변

11

아무도 내가 왜 이런 일이 일어날 수 있는지 설명 할 수 있습니까?

그것은 the docs부터 기록 동작 : 순종있다 : 스케일이 동작에 의해 감소되는 경우

는 실제 크기의 값은 (곱셈은 아니고) 분할되어야하고, 값이 변경 될 수있다; 이 경우 지정된 반올림 모드가 나누기에 적용됩니다.

그리고 RoundingMode.HALF_UP에 대한

:

모두 이웃이 경우 반올림, 등거리하지 않는 한 "가장 가까운 이웃"으로 반올림 모드를 반올림.

지금 7.3149999999999995 는 7.31과 7.32 모두 등거리 아니다 - 그것은 7.31로 더 가까이, 그 결과 그래서.

HALF_UPHALF_DOWN 사이의 차이는 원래 값이 정확히 7.315, 즉 둘 사이의 절반 인 경우에만 나타납니다.

제쳐두고 을 정확히 개로 만들려면 String을 사용하시기 바랍니다. 예를 들어 :

BigDecimaldouble에서 변환
BigDecimal bd = new BigDecimal("0.1"); 

일반적으로 당신이 뭔가 잘못있어 표시이다, 당신은 하나 개의 유형을 사용해야합니다으로

double d = 0.1; 
BigDecimal bd = new BigDecimal(d); 

는 동일하지 않습니다 일관되게.

+2

+1 질문이 실제로 정말 우아한 대답일까요? – Anshu

+2

@Anshu : 앞으로 비슷한 질문을 가진 사람이 HALF_UP 또는 HALF_DOWN을 검색하여이를 찾고이 상황과 비교하기를 바랍니다. –

+0

@ Anshu는 설명에 많은 감사를드립니다. 문제는 C#과 같은 다른 언어가이 값을 7.32로 반올림하고 동일한 논리를 여기에 유지해야한다는 것입니다. 그래서 모든 RoundingModes를 테스트했는데 예상했던대로 작동하지 않았습니다 ... – regisxp

1

ROUND_HALF_UP : 두 이웃이 등거리에 있지 않으면 "가장 가까운 이웃"을 향해 반올림하는 모드. 당신의 예에서

은 가장 가까운 이웃이다 : 7.314 4이를 증명하기 위해 10 0보다에 가까운 7.31 때문에, .... 7.315에 ... 다른 반올림 모드에서

봐 7.314 변경 당신이 원하는 행동을 제공합니다.

+1

또한 d를 BigDecimal 생성자에서 문자열로 변환하는 대신 BigDecimal을 BigDecimal bd = new BigDecimal (d)로 인스턴스화 할 수 있습니다. –

+0

아니요. BigDecimal 인스턴스에서 double을 사용하는 경우 [반올림 문제] (http://stackoverflow.com/questions/7186204/bigdecimal-to-use-new-orvalueof/9713581)를 소개합니다. – DuncanKinnear