몇 가지 예외사항을 처리해보자.

case 1) 정수 범위를 벗어났을 때 ( bigDecimal )

숫자를 많이 입력했을 때,

계산 결과가 정수 범위를 벗어났을 때

결과 확인 시, 앱이 종료됨

 

LogCat 을 살펴보자.

넘버포멧익셉션.

Caused by: java.lang.NumberFormatException: For input string: "123456789123456789" at java.lang.Integer.parseInt(Integer.java:618)

 

integer 의 범위를 벗어나는 문제를 해결하기 위해 사용할 수 있는 것이

bigDecimal 이다.

소수점이 잘 처리되지 않는 부분, 부동 소수점 관련은 bigDecimal

 

자바와 코틀린에서 소수점을 정확히 계산하려면

integer, long, float, doouble 같은 primitive type 이 아닌

bigDecimal 타입을 사용해야 한다.


 

bigDecimal 형은

무한대에 가까운 아주 큰 수를 입력 받아도 잘 계산하며

소수점 계산도 정확하다.

 


아래 MainActivity.kt 코드에서

toInt() 를 toBigDecimal() 로 수정하자.

val firstNumber = firstNumberText.toString().toInt()
val secondNumber = secondNumberText.toString().toInt()
val firstNumber = firstNumberText.toString().toBigDecimal()
val secondNumber = secondNumberText.toString().toBigDecimal()

 

case 2) 맨 앞 숫자가 0 & 세 자리마다 끊기 ( DecimalFormat )

맨 앞 숫자가 0이면 0이 사라져야하고

세 자리마다 콤마(,)를 넣어 시안성을 높여보자.

 

decimalFormat 변수 선언 및 초기화

private val decimalFormat = DecimalFormat("#,###") 
// #.## 소수점까지 포맷 지정 가능

 

 

ui 업데이트 함수 수정

updateEquationTextView()

// ui 업데이트 함수
private fun updateEquationTextView() {
    val firstFormattedNumber = if(firstNumberText.isNotEmpty()) decimalFormat.format(firstNumberText.toString().toBigDecimal()) else ""
    val secondFormattedNumber = if(secondNumberText.isNotEmpty()) decimalFormat.format(secondNumberText.toString().toBigDecimal()) else ""

    binding.equationTextView.text = "$firstFormattedNumber $operatorText $secondFormattedNumber"
}

 

equalClicked 함수의 result 수정

equalClicked()

val result = when(operatorText.toString()){
    "+" -> decimalFormat.format(firstNumber + secondNumber)
    "-" -> decimalFormat.format(firstNumber - secondNumber)
    else -> "잘못된 수식 입니다."
}

 

두 가지 예외 처리를 해보았다.

다음 단원에서는 UI를 조금 더 꾸며보도록 하자.


3) 코드 및 결과

MainActivity.kt

package com.part1.chapter5

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.Toast
import com.part1.chapter5.databinding.ActivityMainBinding
import java.text.DecimalFormat

class MainActivity : AppCompatActivity() {
    private lateinit var binding : ActivityMainBinding
    private val firstNumberText = StringBuilder("")
    private val secondNumberText = StringBuilder("")
    private val operatorText = StringBuilder("")
    private val decimalFormat = DecimalFormat("#,###") // #.## 소수점까지

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }

    // xml 에서 접근할 수 있어야 하므로, public 으로 지정
    // 매개변수를 View 로 받으므로, 반드시 매개변수 쓰기
    fun numberClicked(view : View) {
        // Log.d("numberClicked", "one")
        // button 에서 누른 숫자 추출
        // 모든 view 가 text 라는 attribute 를 가지고 있지 않다.
        // view 가 버튼이라면, text를 string 으로 변환
        // view 가 Null 이 아니면, text 값을 받아 string 형으로 변환
        // 버튼이 아니면 빈문자열 ""
        val numberString = (view as? Button)?.text?.toString() ?: ""

        // 첫 번째 숫자일지, 두 번째 숫자일지 확인
        // 첫 번째 숫자와 연산자가 없으면, 첫 번째 숫자
        val numberText = if(operatorText.isEmpty()) firstNumberText else secondNumberText

        numberText.append(numberString)

        // ui 업데이트
        updateEquationTextView()
    }

    fun clearClicked(view : View) {
        firstNumberText.clear()
        secondNumberText.clear()
        operatorText.clear()
        updateEquationTextView() // ui 업데이트
        binding.resultTextView.text =""
    }

    fun equalClicked(view : View) {
        if(firstNumberText.isEmpty() || secondNumberText.isEmpty() || operatorText.isEmpty()) {
            Toast.makeText(this, "올바르지 않은 수식 입니다.", Toast.LENGTH_SHORT).show()
            return
        }
        val firstNumber = firstNumberText.toString().toBigDecimal()
        val secondNumber = secondNumberText.toString().toBigDecimal()

        val result = when(operatorText.toString()){
            "+" -> decimalFormat.format(firstNumber + secondNumber)
            "-" -> decimalFormat.format(firstNumber - secondNumber)
            else -> "잘못된 수식 입니다."
        }
        binding.resultTextView.text = result

        updateEquationTextView()
    }

    fun operatorClicked(view : View) {
        val operatorString = (view as? Button)?.text?.toString() ?: ""

        // 첫 번째 숫자를 입력받지 못하면,
        if(firstNumberText.isEmpty()) {
            Toast.makeText(this, "먼저 숫자를 입력해주세요.", Toast.LENGTH_SHORT).show()
            return
        }

        // 두 번째 숫자까지 입력받았으면,
        if(secondNumberText.isNotEmpty()){
            Toast.makeText(this, "1개의 연산자에 대해서만 연산이 가능합니다.", Toast.LENGTH_SHORT).show()
            return
        }

        operatorText.append(operatorString)
        updateEquationTextView() // ui 업데이트
    }

    // ui 업데이트 함수
    private fun updateEquationTextView() {
        val firstFormattedNumber = if(firstNumberText.isNotEmpty()) decimalFormat.format(firstNumberText.toString().toBigDecimal()) else ""
        val secondFormattedNumber = if(secondNumberText.isNotEmpty()) decimalFormat.format(secondNumberText.toString().toBigDecimal()) else ""

        binding.equationTextView.text = "$firstFormattedNumber $operatorText $secondFormattedNumber"
    }

}

+ Recent posts