java (덧셈/뺄셈)에서 두 개의 double
값을 처리 할 때 최대 정밀도 손실을 설정하는 것이 가능합니까? 아마도 최악의 시나리오는 두 개의 숫자가 정확히 표현 될 수없는 경우이며, 그 다음에는 연산이 수행되어 정확하게 표현 될 수없는 값을 얻게됩니다.자바 - 하나의 더블 덧셈/뺄셈에서 최대 정밀도 손실
답변
Math.ulp(double)
을 살펴보십시오. ulp이 double
인 것은 다음으로 높은 값으로의 델타입니다. 예를 들어, 숫자에 더하고 하나가 다른 숫자의 ulp보다 작 으면 추가가 효과가 없음을 알 수 있습니다. 두 개의 double을 곱하면 결과의 최대 오차를 얻기 위해 ulps를 곱할 수 있습니다.
이것은 정확히 원했던 것입니다. – Bober02
모두 정밀도가 손실 될 수 있습니다. 예를 들어 결과가 가장 큰 표현 가능한 유한 수보다 클 경우에 발생할 수 있습니다. 그런 다음 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
표현 오류의 크기가 숫자의 크기에 비례합니다.
당신은 출력 아래의 예를 들어 코드, 사용자의 입력의 실제 정밀도를 살펴 가질 수위의 편집 내용보기 - 대부분 추가 사항입니다 ... – Bober02
:
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 등)에서는 작동하지 않습니다.
정밀도 손실이 문제가되는 경우 double 대신 BigDecimal을 사용하는 것이 좋습니다. –
네,이 질문의 요점은 손실이 얼마나 큰지를 보는 것입니다. double은 8 바이트를 차지하지만 BigDecimal은 약 40이고 많은 데이터 포인트를 저장해야합니다. – Bober02
많은 부동 소수점 연산을 수행 할 때 객체 대신 프리미티브를 사용하면 성능이 향상 될 수 있습니다. – Cephalopod