알 리 바 바 가 왜 BigDecimal 의 equals 방법 을 사용 하여 등가 비 교 를 금지 하 는 지 상세 하 게 설명 하 다.

6051 단어 BigDecimalequals
BigDecimal 은 많은 사람들 에 게 낯 설 지 않 고 많은 사람들 이 그의 용법 을 알 고 있다 고 믿 습 니 다.이것 은 자바.math 가방 에서 제공 하 는 정확 한 연산 을 할 수 있 는 유형 입 니 다.
금액 표시,금액 계산 등 을 진행 하 는 장면 에 서 는 더 블,플 로 트 등 을 사용 할 수 없고 정밀도 에 더 잘 지원 되 는 빅 데 시 밀 을 사용 해 야 한 다 는 것 을 많은 사람들 이 알 고 있다.
그래서 많은 결제,전자상거래,금융 등 업무 에서 빅 데 시 멜 의 사용 이 매우 빈번 하 다.그리고 이것 은 매우 사용 하기 좋 은 유형 이 라 고 할 수 밖 에 없다.그 내 부 는 여러 가지 방법 을 가지 고 있다.예 를 들 어 더하기,빼 기,곱 하기,제외 등 연산 방법 은 모두 직접 호출 할 수 있다.
BigDecimal 로 숫자 를 표시 하고 숫자 연산 을 해 야 하 는 것 외 에 코드 에 서 는 숫자 에 대한 동일 한 판단 이 자주 필요 하 다.
이 지식 에 대해 최신 판 알 리 바 바 자바 개발 매 뉴 얼 에 도 설명 되 어 있다.

이 뒤의 사 고 는 무엇 입 니까?
나 는 이전의 CodeReview 에서 다음 과 같은 저급한 오 류 를 본 적 이 있다.

if(bigDecimal == bigDecimal1){
  //      
}
이런 오 류 는 똑똑 하 다 고 믿 는 독자 들 이 한눈 에 문 제 를 알 수 있다.빅 디 밀 이 대상 이기 때문에 두 숫자의 값 이 같 는 지 아 닌 지 를 4 만 567914 로 판단 할 수 없다.
상기 와 같은 문 제 는 일정한 경험 이 있 는 후에 도 피 할 수 있 지만 똑똑 한 독자 들 은 다음 과 같은 코드 를 보 세 요.그 에 게 문제 가 있다 고 생각 합 니까?

if(bigDecimal.equals(bigDecimal1)){
  //      
}
이상 의 이런 표기 법 은 당신 이 예상 한 것 과 다 를 수 있 음 을 명확 하 게 알려 드릴 수 있 습 니 다!
먼저 실험 을 하고 다음 코드 를 실행 합 니 다.

BigDecimal bigDecimal = new BigDecimal(1);
BigDecimal bigDecimal1 = new BigDecimal(1);
System.out.println(bigDecimal.equals(bigDecimal1));


BigDecimal bigDecimal2 = new BigDecimal(1);
BigDecimal bigDecimal3 = new BigDecimal(1.0);
System.out.println(bigDecimal2.equals(bigDecimal3));


BigDecimal bigDecimal4 = new BigDecimal("1");
BigDecimal bigDecimal5 = new BigDecimal("1.0");
System.out.println(bigDecimal4.equals(bigDecimal5));
이상 코드,출력 결 과 는:
true
true
false
BigDecimal 의 equals 원리
상기 코드 예 시 를 통 해 우 리 는 BigDecimal 의 equals 방법 으로 1 과 1.0 을 비교 할 때 어떤 때 는 true(int,double 로 BigDecimal 을 정의 할 때),어떤 때 는 false(String 으로 BigDecimal 을 정의 할 때)를 발견 했다.
그렇다면 왜 이런 상황 이 벌 어 졌 을 까?빅 데 시 멜 의 equals 방법 부터 살 펴 보 자.
BigDecimal 의 자바 독 에 서 는 그 이 유 를 설명 했다.
Compares this BigDecimal with the specified Object for equality. Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by this method)
대충 말 하면 equals 방법 과 compare To 는 다 르 고 equals 방법 은 두 부분 을 비교 하 는데 각각 값(value)과 정밀도(scale)이다.
대응 하 는 코드 는 다음 과 같 습 니 다.

그래서 우리 가 상기 코드 에서 정의 한 두 개의 BigDecimal 대상(bigDecimal 4 와 bigDecimal 5)의 정밀도 가 다 르 기 때문에 equals 를 사용 하여 비교 한 결 과 는 false 입 니 다.
코드 를 debug 하려 고 시도 합 니 다.debug 과정 에서 우 리 는 bigDecimal 4 의 정밀도 가 0 이 고 bigDecimal 5 의 정밀도 가 1 입 니 다.

여기 서 우 리 는 equals 가 bigDecimal 4 와 bigDecimal 5 를 비교 한 결과 false 인 이 유 는 정밀도 가 다 르 기 때 문 이 라 고 대충 설명 했다.
그렇다면 왜 정밀도 가 다 릅 니까?왜 bigDecimal 2 와 bigDecimal 3 의 정밀도 가 같 습 니까?
왜 정밀도 가 다 릅 니까?
이것 은 BigDecimal 의 정밀도 문제 와 관련된다.이 문 제 는 사실 비교적 복잡 하 다.본문의 중점 이 아니 기 때문에 이 안 에는 간단하게 소개 하 자.모두 가 흥 미 를 느끼 면 뒤에 따로 이야기 합 시다.
우선 빅 디 밀 은 다음 과 같은 4 가지 구조 방법 이 있다.

BigDecimal(int)
BigDecimal(double) 
BigDecimal(long) 
BigDecimal(String)
상기 네 가지 방법 으로 만들어 진 빅 데 시 멜 의 정밀 도 는 다르다.
BigDecimal(long)과 BigDecimal(int)
우선,가장 쉬 운 것 은 BigDecimal(long)과 BigDecimal(int)입 니 다.정수 이기 때문에 정밀도 가 0 입 니 다.

public BigDecimal(int val) {
  this.intCompact = val;
  this.scale = 0;
  this.intVal = null;
}

public BigDecimal(long val) {
  this.intCompact = val;
  this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
  this.scale = 0;
}
BigDecimal(double)
한편,BigDecimal(double)에 대해 우리 가 new BigDecimal(0.1)을 사용 하여 BigDecimal 을 만 들 었 을 때 사실은 만들어 진 값 은 0.1 과 같은 것 이 아니 라 0.100000000000000055511151231257821181583454115625 이다.이것 은 doule 자체 가 표시 한 것 이 단지 근사치 이기 때문이다.
그러면 우리 가 new BigDecimal(0.1)을 사용 하 든 new BigDecimal(0.10)의 정 의 를 사용 하 든 그의 유사 치 는 모두 0.1000000000000000555111527272727181583454115625 라 는 것 이다.그러면 그의 정 도 는 바로 이 숫자의 자릿수,즉 55 이다.

다른 부동 소수점 도 마찬가지다.new BigDecimal(1.0)과 같은 형식 으로 볼 때 그 는 본질 적 으로 정수 이기 때문에 그 가 만 든 숫자의 정밀도 가 0 이다.
그래서 빅 디 밀(1.0)과 빅 디 밀(1.00)의 정밀도 가 같 기 때문에 equals 방법 으로 비교 할 때 얻 은 결 과 는 트 루 다.
BigDecimal(string)
그리고 BigDecimal(double)에 대해 우리 가 new BigDecimal(0.1)을 사용 하여 BigDecimal 을 만 들 었 을 때 사실은 만 든 값 은 0.1 과 같 습 니 다.그럼 그의 정밀 도 는 1 이다.
new BigDecimal("0.10000")을 사용 하면 만 든 수 는 0.10000 이 고 정밀도 가 5 입 니 다.
그래서 빅 디 밀('1.0')과 빅 디 밀('1.00')의 정밀도 가 다 르 기 때문에 equals 방법 으로 비교 할 때 얻 은 결 과 는 false 다.
어떻게 BigDecimal 을 비교 합 니까?
앞에서 우 리 는 BigDecimal 의 equals 방법 을 설 명 했 는데 사실은 숫자의 값 을 비교 할 뿐만 아니 라 그 정밀 도 를 비교 할 수 있다.
그래서 우리 가 equals 방법 으로 두 수의 일치 여 부 를 판단 할 때 매우 엄격 하 다.
그렇다면 우리 가 두 빅 디 밀 값 이 같은 지 판단 하고 싶다 면 어떻게 판단 해 야 할 까?
BigDecimal 에서 compare To 방법 을 제 공 했 습 니 다.이 방법 은 두 숫자의 값 만 비교 할 수 있 습 니 다.두 숫자 가 같 으 면 0 으로 돌아 갑 니 다.

BigDecimal bigDecimal4 = new BigDecimal("1");
  BigDecimal bigDecimal5 = new BigDecimal("1.0000");
  System.out.println(bigDecimal4.compareTo(bigDecimal5));
이상 코드,출력 결과:
0
그 소스 코드 는 다음 과 같다.

총결산
BigDecimal 은 높 은 정밀도 의 숫자 를 나타 내 는 데 매우 좋 은 유형 으로 풍부 한 방법 을 제공 합 니 다.
그러나 그의 equals 방법 을 사용 할 때 신중 해 야 한다.왜냐하면 그 는 비교 할 때 두 숫자의 값 을 비교 할 뿐만 아니 라 그들의 정밀도 도 비교 할 수 있 기 때문이다.이 두 가지 요소 중 하나 가 같 지 않 으 면 결과 도 false 이다.
독자 가 두 개의 BigDecimal 수 치 를 비교 하려 면 compare To 방법 을 사용 할 수 있다.
알 리 바 바 가 왜 BigDecimal 의 equals 방법 을 사용 하 는 것 을 금지 하 는 지 에 대한 자세 한 설명 은 여기까지 입 니 다.더 많은 관련 금지 BigDecimal equals 방법 등 값 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부탁드립니다!

좋은 웹페이지 즐겨찾기