ArithmeticException :“비 종료 소수점 확장; 정확하게 표현할 수있는 소수 결과가 없습니다”
다음 코드가 아래에 표시된 예외를 발생시키는 이유는 무엇입니까?
BigDecimal a = new BigDecimal("1.6");
BigDecimal b = new BigDecimal("9.2");
a.divide(b) // results in the following exception.
-
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
로부터 자바 8 문서 :
MathContext 객체에 정밀도 설정 0 (예 : MathContext.UNLIMITED)이 제공되면 MathContext 객체를 사용하지 않는 산술 메서드와 마찬가지로 산술 연산이 정확합니다. (이것은 5 이전 릴리스에서 지원 된 유일한 동작입니다.)
정확한 결과를 계산 한 결과, 정밀도 설정이 0 인 MathContext 객체의 반올림 모드 설정은 사용되지 않으므로 관련이 없습니다. 나누기의 경우 정확한 몫은 무한 길이의 십진수 확장을 가질 수 있습니다. 예를 들어 1을 3으로 나눈 값입니다.
몫에 끝나지 않는 10 진수 확장이 있고 정확한 결과를 반환하도록 연산이 지정된 경우 ArithmeticException이 발생합니다. 그렇지 않으면 다른 작업에서와 같이 정확한 분할 결과가 반환됩니다.
수정하려면 다음과 같이해야합니다 .
a.divide(b, 2, RoundingMode.HALF_UP)
where 2 is scale and RoundingMode.HALF_UP is rounding mode
자세한 내용은 http://jaydeepm.wordpress.com/2009/06/04/bigdecimal-and-non-terminating-decimal-expansion-error/
정밀도와 반올림 모드를 지정하지 않기 때문입니다. BigDecimal은 10, 20, 5000 또는 무한 소수점 자리를 사용할 수 있으며 여전히 숫자를 정확하게 표현할 수는 없다고 불평합니다. 따라서 잘못된 BigDecimal을 제공하는 대신 사용자에게 윙윙 거리는 소리입니다.
그러나 RoundingMode와 정밀도를 제공하면 (예 : 1.333333333에서 무한대를 1.3333과 같은 것으로 변환 할 수 있지만 ... 프로그래머는 당신이 어떤 정밀도에 만족하는지 말할 필요가 있습니다 '.
넌 할 수있어
a.divide(b, MathContext.DECIMAL128)
32,64,128 중 원하는 비트 수를 선택할 수 있습니다.
이 링크를 확인하십시오 :
이러한 문제를 해결하기 위해 아래 코드를 사용했습니다.
a.divide(b, 2, RoundingMode.HALF_EVEN)
2는 정밀도입니다. 이제 문제가 해결되었습니다.
내 코드 줄이 다음과 같기 때문에 동일한 문제가 발생했습니다.
txtTotalInvoice.setText(var1.divide(var2).doubleValue() + "");
십진수 정밀도를 쓰지 않았기 때문에 이전 답변을 읽는 것으로 변경합니다.
txtTotalInvoice.setText(var1.divide(var2,4, RoundingMode.HALF_UP).doubleValue() + "");
4는 10 진법
AND RoundingMode는 Enum 상수이며,이 중 하나를 선택할 수 있습니다 UP, DOWN, CEILING, FLOOR, HALF_DOWN, HALF_EVEN, HALF_UP
이 경우 HALF_UP의 결과는 다음과 같습니다.
2.4 = 2
2.5 = 3
2.7 = 3
RoundingMode
여기 에서 정보 를 확인할 수 있습니다 : http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
결과를 반올림하는 문제는 나를위한 해결책은 다음과 같습니다.
divider.divide(dividend,RoundingMode.HALF_UP);
BigDecimal에 대한 답변에서 ArithmeticException이 발생 함
public static void main(String[] args) {
int age = 30;
BigDecimal retireMentFund = new BigDecimal("10000.00");
retireMentFund.setScale(2,BigDecimal.ROUND_HALF_UP);
BigDecimal yearsInRetirement = new BigDecimal("20.00");
String name = " Dennis";
for ( int i = age; i <=65; i++){
recalculate(retireMentFund,new BigDecimal("0.10"));
}
BigDecimal monthlyPension = retireMentFund.divide(
yearsInRetirement.divide(new BigDecimal("12"), new MathContext(2, RoundingMode.CEILING)), new MathContext(2, RoundingMode.CEILING));
System.out.println(name+ " will have £" + monthlyPension +" per month for retirement");
}
public static void recalculate (BigDecimal fundAmount, BigDecimal rate){
fundAmount.multiply(rate.add(new BigDecimal("1.00")));
}
나누기 메소드 호출에 MathContext 객체를 추가하고 정밀도 및 반올림 모드를 조정하십시오. 문제를 해결해야합니다
Bigdecimal이 손실되지 않았기 때문에, 예를 들어 1/3을 나누면 무한대로 10 진수가 반복됩니다. 0.33333333 ... 이론적으로 다시 곱하면 정확한 결과가 나타납니다. 그러나 무한대 숫자는 스택 오버 플로우를 생성하며이 경우 예외가 시작됩니다.
해결책 :
try {
result = n1.divide(n2);
} catch (ArithmeticException e){
Log.d("Error bigdecimal", e.toString());
result = (n1.doubleValue() / n2.doubleValue());
};
또는
n1.divide(n2,RoundingMode.HALF_UP);
이 경우 결과는 반올림으로 잘리지 않습니다.
프로그램은 십진수의 정밀도를 알지 못하므로 다음을 throw합니다.
java.lang.ArithmeticException: Non-terminating decimal expansion
예외를 우회하는 솔루션 :
MathContext precision = new MathContext(int setPrecisionYouWant); // example 2
BigDecimal a = new BigDecimal("1.6",precision);
BigDecimal b = new BigDecimal("9.2",precision);
a.divide(b) // result = 0.17
'development' 카테고리의 다른 글
Visual Studio“Any CPU”대상은 무엇을 의미합니까? (0) | 2020.02.14 |
---|---|
"[False, True]의 not (True)"이 False를 반환하는 이유는 무엇입니까? (0) | 2020.02.14 |
LINQ를 사용하여 하나의 List <>에서 다른 List <>에없는 항목을 가져옵니다. (0) | 2020.02.14 |
개체가 비어 있습니까? (0) | 2020.02.14 |
MySQL에서 정규 표현식을 바꾸는 방법은 무엇입니까? (0) | 2020.02.14 |