BigDecimal을 반환하는 최대 절전 모드 메서드가 있습니다. 해당 번호를 전달 해야하는 다른 API 메소드가 있지만 Integer를 매개 변수로 허용합니다. 두 메소드의 리턴 유형 또는 변수 유형을 변경할 수 없습니다.
이제 BigDecimal을 Integer로 변환하고 두 번째 방법으로 전달하는 방법은 무엇입니까?
이 방법이 있습니까?
답변
당신은 myBigDecimal.intValueExact()
(또는 그냥 intValue()
) 전화 하고 정보를 잃을 경우 예외를 던질 것입니다. 그것은 int를 반환하지만 autoboxing은 그것을 처리합니다.
답변
BigDecimal
보다 큰 값을 포함하지 않을 것이라고 보장 할 수 있습니까 Integer.MAX_VALUE
?
그렇다면 코드 호출은 intValue
다음과 같습니다.
Integer.valueOf(bdValue.intValue())
답변
TL; DR
보편적 인 전환 요구를 위해 이들 중 하나를 사용하십시오
//Java 7 or below
bigDecimal.setScale(0, RoundingMode.DOWN).intValueExact()
//Java 8
bigDecimal.toBigInteger().intValueExact()
추리
대답은 요구 사항이 무엇이며 이러한 질문에 어떻게 대답 하느냐에 달려 있습니다.
- 는 것이다
BigDecimal
잠재적으로 비 제로 소수 부분이 있습니까? - 는 것이다
BigDecimal
잠재적에 맞지Integer
범위? - 0이 아닌 소수 부분을 둥글거나 잘게 하시겠습니까?
- 0이 아닌 분수 부분은 어떻게 반올림 하시겠습니까?
처음 두 가지 질문에 대답하지 않으면 BigDecimal.intValueExact()
다른 사람들이 제안한대로 사용 하고 예상치 못한 일이 발생했을 때 터질 수 있습니다.
2 번 문제에 대해 100 % 확신이 없다면, 항상 정답 intValue()
이 아닙니다 .
더 나은 만들기
다른 답변을 기반으로 다음 가정을 사용합시다.
- 우리는 정밀도를 잃고 값을 자르는 것으로 괜찮습니다. 그것이
intValueExact()
자동 권투 기능 이기 때문입니다. - 상위 비트를 떨어 뜨릴 때 발생하는 랩을 매우 구체적으로 필요로하지 않는 한 다른 것이 미친 것이기 때문에 범위
BigDecimal
보다 큰 경우 예외가 발생합니다Integer
.
이러한 매개 변수가 주어지면 intValueExact()
소수 부분이 0이 아닌 경우 원하지 않는 경우 예외가 발생합니다. 반면에 intValue()
우리 BigDecimal
가 너무 클 경우 예외를 던지지 마십시오 .
두 세계를 모두 활용하려면 BigDecimal
첫 번째를 반올림 한 다음 변환하십시오. 또한 반올림 프로세스를보다 효과적으로 제어 할 수 있다는 이점이 있습니다.
스팍 그루비 테스트
void 'test BigDecimal rounding'() {
given:
BigDecimal decimal = new BigDecimal(Integer.MAX_VALUE - 1.99)
BigDecimal hugeDecimal = new BigDecimal(Integer.MAX_VALUE + 1.99)
BigDecimal reallyHuge = new BigDecimal("10000000000000000000000000000000000000000000000")
String decimalAsBigIntString = decimal.toBigInteger().toString()
String hugeDecimalAsBigIntString = hugeDecimal.toBigInteger().toString()
String reallyHugeAsBigIntString = reallyHuge.toBigInteger().toString()
expect: 'decimals that can be truncated within Integer range to do so without exception'
//GOOD: Truncates without exception
'' + decimal.intValue() == decimalAsBigIntString
//BAD: Throws ArithmeticException 'Non-zero decimal digits' because we lose information
// decimal.intValueExact() == decimalAsBigIntString
//GOOD: Truncates without exception
'' + decimal.setScale(0, RoundingMode.DOWN).intValueExact() == decimalAsBigIntString
and: 'truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception'
//BAD: hugeDecimal.intValue() is -2147483648 instead of 2147483648
//'' + hugeDecimal.intValue() == hugeDecimalAsBigIntString
//BAD: Throws ArithmeticException 'Non-zero decimal digits' because we lose information
//'' + hugeDecimal.intValueExact() == hugeDecimalAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'' + hugeDecimal.setScale(0, RoundingMode.DOWN).intValueExact() == hugeDecimalAsBigIntString
and: 'truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception'
//BAD: hugeDecimal.intValue() is 0
//'' + reallyHuge.intValue() == reallyHugeAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'' + reallyHuge.intValueExact() == reallyHugeAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'' + reallyHuge.setScale(0, RoundingMode.DOWN).intValueExact() == reallyHugeAsBigIntString
and: 'if using Java 8, BigInteger has intValueExact() just like BigDecimal'
//decimal.toBigInteger().intValueExact() == decimal.setScale(0, RoundingMode.DOWN).intValueExact()
}
답변
글쎄, 당신은 전화 할 수 있습니다 BigDecimal.intValue()
:
이 BigDecimal를 정수로 변환합니다. 이 변환은 Java 언어 사양에 정의 된대로 double에서 short로 좁히는 기본 변환과 유사합니다.이 BigDecimal의 소수 부분은 모두 버리고 결과 “BigInteger”가 int에 맞지 않을 경우에는 낮음 32 비트가 반환됩니다. 이 변환은이 BigDecimal 값의 전체 크기와 정밀도에 대한 정보를 잃을 수 있으며 반대 부호와 함께 결과를 리턴 할 수 있습니다.
Integer.valueOf(int)
최신 버전의 Java를 사용하는 경우 명시 적으로 전화를 걸 거나 자동 박싱 기능을 사용할 수 있습니다.
답변
다음은 트릭을 수행해야합니다.
BigDecimal d = new BigDecimal(10);
int i = d.intValue();