Java에서 플로팅 포인트 번호를 사용할 때 Double은 때때로 사고 또는 부정확 한 결과를 생성한다는 것을 알 수 있습니다. 이 동작은 특히 금융 응용 프로그램 또는 고전성 시나리오에서 오류를 일으킬 수 있습니다.
이 기사에서는이 문제의 근본 원인을 탐색하고 피하는 방법을 설명하고, 실현 가능한 예를 제공하며, 업데이트 된 Java 버전이 더 나은 대안 솔루션을 제공하는지 논의 할 것입니다.
이중은 정확도를 잃어 버리는 이유는 무엇입니까?
1. IEEE 754 플로팅 포인트 번호 표준
Java의 이중 데이터 유형은 IEEE 754 플로팅 -Point 번호 계산 표준을 따릅니다. 다음 방법을 사용하여 이진 형식으로 숫자를 나타냅니다.
1 Digit 기호의 경우
11 자리
인덱스에 사용되는
52 -Bit 점수 (꼬리 번호)에 사용됩니다.
이 이진 명령문은 제한 사항을 도입했습니다
제한된 정확도 : Double은 최대 15-17 비트 10 진수 숫자 만 정확하게 나타낼 수 있습니다.
통합 오류 : 많은 소수점 점수 (예 : 0.1)는 이진수로 정확하게 표현할 수 없으며, 이는 스포드 오류로 이어집니다.
예를 들어, 바이너리에서 :
0.1은 무제한주기 소수점이되어 저장을 위해 차단되어 약간의 부정확성이 도입됩니다. -
2. 산술 연산에서의 누적 오류
이중과 관련된 작업은 오류를 축적 할 수 있습니다.
> 반복 첨가/축소 방법은 입력 오류를 증폭시킵니다.
> 곱셈/제거는 잘림으로 인해 정확도를 잃을 수 있습니다. -
이 동작은 자바 고유가 아닌 부동 포인트 숫자에 내재되어 있습니다.
실행 가능한 예 : Double
로 인한 정확도의 정확도
이것은 데모 문제의 예입니다.
출력 :
결과 0.30000000000000004 이진 표현으로 인한 스포드 오류를 강조합니다. 차이가 약간 중요하지 않더라도 주요 시스템에서 주요 문제가 발생할 수 있습니다. -
정확도 손실을 피하는 방법
1. 정확한 계산을 위해 BigDecimal을 사용하십시오
Java의 Bigdecimal 클래스는 임의의 정확도 산술을 제공하므로 높은 정확도 (예 : 금융 컴퓨팅)가 필요한 이상적인 선택입니다.
-
Bigdecimal을 사용하는 예 :
출력 :
Bigdecimal을 사용함으로써 정확도 문제가 제거되었고 올바른 결과를 비교했습니다.
2. Epsilon 값을 사용하여 를 비교하십시오
정확도 손실을 다루는 또 다른 방법은 플로팅 포인트의 수를 공차 (Epsilon)와 비교하는 것입니다. 이 방법은 정확한 동등한 특성에 따라 숫자가 "충분히 가까운 지 여부를 확인합니다.
Epsilon 비교를 사용하는 예 :
<code class="language-java">public class DoublePrecisionLoss {
public static void main(String[] args) {
double num1 = 0.1;
double num2 = 0.2;
double sum = num1 + num2;
System.out.println("预期和:0.3");
System.out.println("实际和:" + sum);
// 比较
if (sum == 0.3) {
System.out.println("和等于0.3");
} else {
System.out.println("和不等于0.3");
}
}
}</code>
로그인 후 복사
왜 Epsilon을 사용하여 비교합니까?
유연성 : 통합 오류로 인한 작은 차이를 허용합니다. -
단순 :이 방법에는 외부 라이브러리가 필요하지 않으며 효율성이 높습니다.
-
Apache Commons Math를 사용하여 정확도를 향상시킵니다
Apache Commons Math는 복잡한 수학 컴퓨팅을 위해 설계된 라이브러리입니다. Bigdecimal과 같은 임의의 정확도 산술을 제공하지는 않지만 수치 작업을 단순화하고 일부 경우 부동 -지점 오류를 최소화하는 실제 절차를 제공합니다.
예 : Precision.equals를 사용하여
를 비교하십시오
출력 :
왜 Apache Commons 수학을 사용합니까?
단순화 된 비교
: 정전.
Lightweight
: 라이브러리는 Bigdecimal의 비용을 늘리지 않고 수치 계산에 중점을 둔 도구를 제공합니다. <code>预期和:0.3
实际和:0.30000000000000004
和不等于0.3</code>
로그인 후 복사
요약
한계 이해 : 이중 자체는 결함이 없지만 이진 부동 소수점 표현이기 때문에 높은 예정 작업에 적합하지 않습니다. <code class="language-java">import java.math.BigDecimal;
public class BigDecimalExample {
public static void main(String[] args) {
BigDecimal num1 = new BigDecimal("0.1");
BigDecimal num2 = new BigDecimal("0.2");
BigDecimal sum = num1.add(num2);
System.out.println("预期和:0.3");
System.out.println("实际和:" + sum);
// 比较
if (sum.compareTo(new BigDecimal("0.3")) == 0) {
System.out.println("和等于0.3");
} else {
System.out.println("和不等于0.3");
}
}
}</code>
로그인 후 복사
bigdecimal : bigdecimal은 정확성을 보장 할 수 있지만 재무 또는 중요한 계산의 성능에 영향을 줄 수 있습니다.
라이브러리 사용 : Apache Commons Math는 Precision.equals와 같은 실용적인 프로그램을 제공하며, 이는 플로팅 포인트 비교를 효과적으로 처리 할 수 있습니다.
이중 및 대안을 이해함으로써보다 강력하고 정확한 Java 응용 프로그램을 작성할 수 있습니다.
두 배의 정확도와 이러한 문제를 해결하는 방법에 직면하면 의견에 알려주십시오! ?
위 내용은 double이 정밀도를 잃는 이유와 Java에서 이를 방지하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!