문제 설명
Java를 사용하여 프로젝트의 부동 소수점 수를 계산할 때, 4.015*100과 같은 계산의 경우 결과는 예상 401.5가 아니라 401.49999999999999999999994였습니다. 이러한 긴 수의 숫자는 디스플레이하기에 비우호적입니다.
문제의 원인 : 부동 소수점 번호 표현
관련 정보에 컨설팅 한 후에는 컴퓨터의 부동 소수점 번호를 정확하게 표현할 수 없기 때문입니다. 예를 들어, 이중 유형 38414.4의 경우 컴퓨터는 다음과 같이 저장합니다.
바이너리로 변환 : 1001011001110.01100110011001100110011001100110011001100으로 변환합니다
주제로 변환하십시오
계산 방법 : 1.001011000011100110011001100110011001100110011001100110011001100 × 2^15
이중 인코딩 형식은 다음과 같습니다.
더블 사인 비트 1 자리 단계 코드 11 자리 Mantissa 52 자리
기호 비트 : 양수는 0입니다
주문 코드 : 15는 양수이므로 가장 높은 비트는 1이고 가장 낮은 비트는 마이너스 1, 이는 10000001110입니다.
MANTISSUE : 최고 비트의 기본 1을 제거합니다. 001011000011110011001100110011001100110011001100
결합 된 최종 인코딩은 다음과 같습니다. 0 1000001110 0010110010011001100110011001100110011001100110011001100
여기에서 이진 인코딩이 0.4 = 0.25 + 0.125 + ...과 같이 분수 부품을 정확하게 표현하기가 불가능하게 만들기 때문입니다. 따라서 부동 소수점 번호를 계산할 때 정확도 오류가 발생합니다.
해결책 : 높은 정밀도
Java의 Bigdecimal은 임의의 정밀도로 부동 소수점 번호 작업을 지원할 수 있습니다. "효과적인 Java"라는 책에서 Float와 Double은 과학적 계산 또는 엔지니어링 계산에 사용되는 반면 Java.math.bigdecimal은 상업적 계산에 사용됩니다.
Bigdecimal (Double) 및 Bigdecimal (String)과 같은 Bigdecimal에 대한 많은 구성 방법이 있습니다. 이중 유형 자체가 불완전하게 정확하기 때문에 구조 매개 변수는 정확도가 손실되지 않도록 문자열 유형이라는 점에 유의해야합니다. 따라서 다음과 같이 작성해야합니다. bigdecimal ( "0.02").
이중 유형의 기본 작업은 Bigdecimal에서 찾을 수 있습니다. 또한 BigDecimal은 NumberFormat과 출력을 형식화하는 데 사용될 수도 있습니다.
BigDecimal은 작업을 수행 할 때 새로운 BigDecimal 객체를 생성하므로 두 배에 비해 성능이 더 많은 오버 헤드를 가져옵니다.
고정밀 구현에 대한 예비 연구
그렇다면 Bigdecimal은 어떻게 임의의 정밀도를 나타낼 수 있습니까? 예비 분석 만 있습니다.
먼저 Biginteger의 구현을 살펴 보겠습니다. 일반 int 유형은 32 비트이므로 범위 제한이 있습니다. BigInteger에는 멤버 변수 int [] mag가 있으므로 int 배열이 길수록 모든 크기의 정수를 나타낼 수 있습니다.
BigDecimal의 구현을 살펴 보겠습니다. 공식 소개에 따르면 모든 빅 듀니는 비 척도 × 10^-스케일로 표현 될 수 있다고합니다. UnscaledValue는 소스 코드의 멤버 변수 biginteger intval에 해당하는 모든 크기의 정수입니다. 스케일은 소스 코드의 변수 int 스케일에 해당하는 순서입니다. 이런 식으로 Bigdecimal은 Biginteger를 기반으로 구현됩니다.
위는 편집자가 소개 한 Java의 부동 소수점 정확도 문제에 대한 해결책입니다. 나는 그것이 당신에게 도움이되기를 바랍니다. 궁금한 점이 있으면 메시지를 남겨주세요.