1. 소개
"Effactive Java"책에서 단어를 빌리려면 Float 및 Double 유형의 주요 설계 목표는 과학 컴퓨팅 및 엔지니어링 컴퓨팅을위한 것입니다. 바이너리 플로팅 포인트 작업을 수행하는데, 이는 광대역 수치 범위에서보다 정확한 빠른 근사치를 제공하도록 신중하게 설계되었습니다. 그러나 완전히 정확한 결과를 제공하지 않으며 정확한 결과가 필요한 상황에서는 사용해서는 안됩니다. 그러나 상업적 계산에는 종종 정확한 결과가 필요하며 현재 Bigdecimal은 유용합니다.
2. Bigdecimal 소개
Bigdecimal은 정밀도의 정수 비 규모 및 32 비트 정수 척도로 구성됩니다. 0이거나 양수 인 경우 스케일은 소수점 이후의 자릿수 수입니다. 음수 인 경우 숫자의 비 스케일 값에 음수 스케일 전력 10을 곱합니다. 따라서 BigDecimal으로 표시되는 값은 (UnscaledValue × 10-Scale)입니다.
3. 테스트 코드
3.1 생성자 (기본 테스트 매개 변수 유형은 이중 및 문자열을 가진 두 개의 공통 생성자입니다)
코드 사본은 다음과 같습니다. bigdecimal adouble = new bigdecimal (1.22);
System.out.println ( "이중 값을 가진 구성 :" + adouble);
bigdecimal astring = new bigdecimal ( "1.22");
System.out.println ( "문자열 값을 가진 구성 :" + astring);
출력이 무엇이라고 생각하십니까? 첫 번째 것이 1.22를 출력 할 것이라고 생각하지 않으면 답변을 올바르게 축하합니다. 출력 결과는 다음과 같습니다.
코드를 다음과 같이 복사하십시오. DoubleValue로 구성하십시오 : 1.21999999999999999999999335447408996243029832839658203125
문자열 값으로 구성 : 1.22
JDK에 대한 설명 :
1. 매개 변수 유형 Double이있는 시공 방법의 결과는 예측할 수 없습니다. 일부 사람들은 Java에 Newbigdecimal (0.1)을 작성하여 만든 큰 사람들이 정확히 0.1 (비 규모 값 1, 스케일은 1)과 정확히 같지만 실제로는 0.100000000000000000000000000055511151231257827021181584541515625라고 생각할 수도 있습니다. 이는 0.1을 이중으로 정확하게 표현할 수 없기 때문에 (또는이 경우 유한 길이 이진 십진수로 표현할 수 없음). 이러한 방식으로, 건축 방법으로 전달 된 값은 0.1과 정확히 같지 않습니다 (해당 값과 동일하지만).
2. 반면, 문자열 구조 방법은 완전히 예측 가능합니다. Newbigdecimal ( "0.1")에 쓰면 예상 0.1과 정확히 동일합니다. 따라서, 이에 비해 일반적으로 문자열 생성자를 먼저 사용하는 것이 좋습니다.
3. 이중을 Bigdecimal의 공급원으로 사용해야하는 경우이 생성자는 정확한 변환을 제공합니다. 다음 작업과 동일한 결과를 제공하지 않습니다. 먼저 Double.toString (Double) 메소드를 사용한 다음 BigDecimal (String) 생성자를 사용하여 Double을 문자열로 변환하십시오. 결과를 얻으려면 (이중) 메소드의 정적 값을 사용하십시오.
3.2 추가 작업
코드 사본은 다음과 같습니다. bigdecimal a = new bigdecimal ( "1.22");
System.out.println ( "문자열 값을 가진 구성 :" + a);
bigdecimal b = 새로운 bigdecimal ( "2.22");
A.add (b);
System.out.println ( "aplus b is :" + a);
출력 할 것이라고 생각하기 쉽습니다.
코드를 다음과 같이 복사하십시오 : stringValue로 구성 : 1.22
A 플러스 B : 3.44
그러나 실제로 A는 플러스 B입니다. 1.22
4. 소스 코드 분석
4.1 valueof (doubleval) 방법
다음과 같이 코드를 복사하십시오 : public static bigdecimal valueof (double val) {
// 알림 : Zero Double Returns '0.0'이므로 우리는 할 수 없습니다.
// 상수 0을 사용합니다. 이것은 충분히 중요 할 수 있습니다
// 공장 접근, 캐시 또는 개인 몇 가지를 정당화합니다.
// 상수, 나중에.
returnnew bigdecimal (double.tostring (val)); // JDK 설명에 대한 3.1의 세 번째 요점 참조
}
4.2 추가 (Bigdecimal Augend) 방법을 추가하십시오
public bigdecimal add (bigdecimal augend) {long xs = this.intcompact; // 정수 번호로 표시되는 bigdecimal, 예를 들어 A는 122 길이 ys = augend.intcompact; // biginteger fst = (this.intcompact! = lavated)와 동일합니까? 님이 bigintger의 값을 초기화하고, intval은 bigintger type의 속성을 초기화합니다! ? null : augend.intval; int rscale = this.scale; // 소수점 이하의 장소 long sdiff = (long) rscale -augend.scale; // 소수점 사이의 차이 (sdiff! = 0) {// 소수점이없는 자리가 가장 작은 자리가 가장 작은 장소는 결과입니다. rscale = augend.scale; if (xs ==가 팽창 || (xs = longmultiplypowerten (xs, rase)) == 팽창) fst = bigmultiplypowerten (REAS); } else {int resa = augend.checkscale (sdiff); if (ys == 팽창 || }} if (xs! = 팽창 && ys! = 팽창) {long sum = xs + ys; if ((((sum ^ xs) & (sum ^ ys)))> = 0l) // 오버플로가 있는지 판단합니다. return bigdecimal.valueof (sum, rcale); // bigdecimal의 정적 공장 메소드}를 사용하여 얻은 bigdecimal 인스턴스} if (fst == null) fst = biginteger.valueof (xs); // biginteger의 정적 공장 메소드 인 경우 (snd == null) snd = biginteof (ys); biginteger sum = fst.add (snd); return (fst.signum == snd.signum)? 새로운 bigdecimal (sum, 팽창, rcale, 0) : new bigdecimal (sum, compactvalfor (sum), rcale, 0); // 다른 구조 방법에 의해 얻은 bigdecimal 객체를 반환}}위는 추가 소스 코드에 대한 분석 일뿐입니다. 뺄셈, 곱셈 및 부서는 실제로 새로운 BigDecimal 객체를 반환합니다. Biginteger와 Bigdecimal은 모두 불변이기 때문에 각 작동 단계를 수행 할 때 새로운 객체가 생성됩니다. 따라서 A.add (b); 추가 작업이 수행되지만 A는 추가 작업 후에 값을 저장하지 않습니다. 올바른 사용법은 a = a.add (b) 여야합니다.
5. 요약
(1) 상업적 계산은 Bigdecimal을 사용합니다.
(2) 매개 변수 유형 문자열이있는 생성자를 사용해보십시오.
(3) Bigdecimals는 불변입니다. 각 작동 단계를 수행 할 때 새 객체가 생성됩니다. 따라서 추가, 뺄셈, 곱셈 및 나누기를 수행 할 때는 작업 후에 값을 절약해야합니다.
(4) 우리는 종종 기본 JDK의 일부 구현 세부 사항을 무시하여 오류를 초래하므로 더 많은주의를 기울여야합니다.
참조 : 클래스 빅데스