2017-10-13 10 views
0

this stackoverflow post을 기준으로 다음과 같이 0.59가 아니라 0.60을 출력 할 것으로 예상됩니다.DecimalFormat/RoundingMode.Down 기능에 혼란 스럽습니다. 가장자리 케이스의 경우

import java.math.RoundingMode; 
import java.text.DecimalFormat; 

public class Test { 
    public static void main(String[] args) { 
     double toFormat = 0.6; 
     DecimalFormat formatter = new DecimalFormat("########0.00"); 
     formatter.setRoundingMode(RoundingMode.DOWN); 
     System.out.println(formatter.format(toFormat)); // 0.60 
    } 
} 

0.60의 가장 가까운 부동 소수점 표현은 다음과 0.6 인 0.59999999999999997779553950749686919152736663818359375이다. Java 8에서 DecimalFormat을 RoundingMode.DOWN으로 설정 한 경우 왜이 값을 0.59로 반올림하지 않습니까?

답변

1

서식 코드가 double의 정밀도를 알고 있기 때문에. 클래스 java.text.DigitList의 방법 shouldRoundUp(...)source code에서

참조 코멘트 : FloatingDecimal의 변환 결과의 정확성 에 대한 정보를 텍스트 이진 double 값을 변환 할 때

이 잘못된 반올림 두 번이나 절단을 방지하려면 , 그리고 반올림이 완료되면서이 클래스에서 필요합니다. 아래의 HALF_DOWN, HALF_EVEN, HALF_UP 반올림 규칙

  • : 형식화하는 플로트 또는 더블의 경우, 우리는 FloatingDecimal는 변환을 10 진수로 바이너리에서 무슨 짓을했는지 고려해야합니다.

    타이 케이스를 고려 FloatingDecimal는 를 값 (그 이하인 경우 묶어 동등한 복귀 십진수)을해서 원형 또는 값이 이상일 때, 을 타이의 값을 "잘라"또는 제공 할 수있다 정확하게 이진수가 일 수있는 정확한 십진수는 플로팅 수식 규칙 (이진수 값의 정확한 십진수 을 가짐)을 지정하여 주어진 10 진수 표현식으로 정확히 변환 될 수 있습니다. 이중 이진 값은 소수점 값으로 정확하게 변환 된 경우

    • 후 DigitList 코드는 예상 반올림 규칙을 적용해야합니다.

    • FloatingDecimal이 이미 십진수를 반올림 한 경우 DigitList는 위의 세 가지 반올림 모드 중 하나 인 중 하나에서 값을 다시 올림하지 않아야합니다. FloatingDecimal가 로 진수 값을 절단 한 경우

    • 에 '5'자리를 DigitList 위에서 에서 세 반올림 모드의 모든 값을 반올림 종료한다.

    그렇지 않으면이 그 위치 후 나머지 자리는 우리가 무엇 FloatingDecimal을 고려하지 않아도, maximumDigits 지수 에 자리 숫자의 집합의 마지막 정확히 경우에만 고려되어야 그랬어.

  • 다른 반올림 모드는 이러한 타이 케이스의 영향을받지 않습니다.

  • 항상 정확한 숫자 (예 : BigInteger, Long, ...)로 변환되는 다른 숫자의 경우)에 false로 설정할 필요 부울 alreadyRounded 전달하고 allDecimalDigits 이러한 상황에 적합한 상태 제공 상부 DigitList 호출 스택에서 참 로 설정되어야한다 ..