2012-11-20 6 views
7

java (덧셈/뺄셈)에서 두 개의 double 값을 처리 할 때 최대 정밀도 손실을 설정하는 것이 가능합니까? 아마도 최악의 시나리오는 두 개의 숫자가 정확히 표현 될 수없는 경우이며, 그 다음에는 연산이 수행되어 정확하게 표현 될 수없는 값을 얻게됩니다.자바 - 하나의 더블 덧셈/뺄셈에서 최대 정밀도 손실

+0

정밀도 손실이 문제가되는 경우 double 대신 BigDecimal을 사용하는 것이 좋습니다. –

+0

네,이 질문의 요점은 손실이 얼마나 큰지를 보는 것입니다. double은 8 바이트를 차지하지만 BigDecimal은 약 40이고 많은 데이터 포인트를 저장해야합니다. – Bober02

+0

많은 부동 소수점 연산을 수행 할 때 객체 대신 프리미티브를 사용하면 성능이 향상 될 수 있습니다. – Cephalopod

답변

5

Math.ulp(double)을 살펴보십시오. ulpdouble 인 것은 다음으로 높은 값으로의 델타입니다. 예를 들어, 숫자에 더하고 하나가 다른 숫자의 ulp보다 작 으면 추가가 효과가 없음을 알 수 있습니다. 두 개의 double을 곱하면 결과의 최대 오차를 얻기 위해 ulps를 곱할 수 있습니다.

+0

이것은 정확히 원했던 것입니다. – Bober02

7

모두 정밀도가 손실 될 수 있습니다. 예를 들어 결과가 가장 큰 표현 가능한 유한 수보다 클 경우에 발생할 수 있습니다. 그런 다음 POSITIVE_INFINITY (또는 NEGATIVE_INFINITY)로 저장됩니다.

업데이트에 대해서는 추가로 발생할 수 있습니다.

double a = Double.MAX_VALUE; 
System.out.println(a); 
double b = a + a; 
System.out.println(b); 

결과 :

1.7976931348623157E308 
Infinity 

이 온라인을 참조하십시오 : 일반적으로 ideone

표현 오류의 크기가 숫자의 크기에 비례합니다.

당신은 출력 아래의 예를 들어 코드, 사용자의 입력의 실제 정밀도를 살펴 가질 수
+0

위의 편집 내용보기 - 대부분 추가 ​​사항입니다 ... – Bober02

0

:

input: 0.01000000000000000020816681711721685132943093776702880859375 
range: [0.0099999999999999984734433411404097569175064563751220703125 - 0.010000000000000001942890293094023945741355419158935546875] 
range size: 3.4694469519536141888238489627838134765625E-18 
input: 10000000000000000 
range: [9999999999999998 - 10000000000000002] 
range size: 4 
당신은 여전히 ​​다음의 결과에 손실을 추정 할 필요가
public static void main(String[] args) { 
    printRange(0.01); 
    printRange(10000000000000000d); 
} 

private static void printRange(double d) { 
    long dBits = Double.doubleToLongBits(d); 
    double dNext = Double.longBitsToDouble(dBits + 1); 
    double dPrevious = Double.longBitsToDouble(dBits + -1); 
    System.out.println("input: " + new BigDecimal(d)); 
    System.out.println("range: [" + new BigDecimal(dPrevious) + " - " + new BigDecimal(dNext) + "]"); 
    System.out.println("range size: " + new BigDecimal(dNext - dPrevious)); 
} 

당신의 조작. 그리고 코너 케이스 (Infinity, NaN 등)에서는 작동하지 않습니다.