[java] BigDecimal을 정수로 변환

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();


답변

BigInteger # intValue () 호출을 시도 했습니까 ?


답변