Kotlin에서 BigDecimal사용시 주의점

Picbel·2023년 8월 26일
1

Kotlin

목록 보기
4/4
post-thumbnail

코틀린에서 BigDecimal을 사용하다 겪은 문제에 대한 포스팅입니다.
아래 예제를 확인하여보시면

BigDecimal(1) / BigDecimal(10) = ?

BigDecimal(1).divide(BigDecimal(10)) = ?

어떤 결과값이 나올것 같나요? 둘다 0.1 아니냐구요?

네 아닙니다.

BigDecimal(1) / BigDecimal(10) = 0

BigDecimal(1).divide(BigDecimal(10)) = 0.10

왜 java의 divide를 사용하면 0.1이 나오고 / 사용하면 0이 나올까요?
수학적으로 둘은 다를것이 없는데요.

결과가 다른 이유는 코틀린 오퍼레이터쪽 코드를 보시면 아실수 있습니다

비밀은 this의 스케일에 맞춰서 계산하게 한다는것

BigDecimal(1) / BigDecimal(10) = 0

에서 BigDecimal(1) 스케일에 맞춰 계산하기 때문에 0이 나옵니다.

BigDecimal(1).setScale(2) / BigDecimal(10) = 0.10

위 처럼 BigDecimal(1)의 스케일을 2로 두고 계산하면 0.10으로 출력되는것을 확인하실수 있습니다.

생각보다 놓치기 쉽기 때문에 해결법으로는 3가지 정도가 생각나는데요.
1. BigDecimal의 scale를 설정하기
2. 오퍼레이터 오버라이딩 하기
3. 명시적 devide 함수 사용하기

현재 팀에서는 오퍼레이터가 주는 편리함 또한 강점이라 생각하여 2번 방식을 채택하였습니다.
하지만 프로젝트 전반적으로 적용시키기엔 무리가 있다 판단하여 아래와 같은 확장 인터페이스를 작성하였습니다.

interface BigDecimalExtension {
    operator fun BigDecimal.div(
        divisor: BigDecimal,
    ): BigDecimal = this.divide(divisor, DEFAULT_SCALE, defaultRoundMode)

    companion object {
        val defaultRoundMode = RoundingMode.HALF_UP

        const val DEFAULT_SCALE = 10
    }
}

해당 인터페이스를 Mixin처럼 사용하여 정밀한 계산이 필요한 경우 오퍼레이터를 사용하면서 BigDecimal을 다루고 있습니다.

profile
Software Developer

0개의 댓글