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"
}
}
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 numberClicked(view : View)
xml 에서 접근할 수 있어야 하므로, public 으로 지정
매개변수를 View 로 받으므로, 반드시 매개변수 쓰기
clearClicked
fun clearClicked(view : View) {
firstNumberText.clear()
secondNumberText.clear()
operatorText.clear()
updateEquationTextView() // ui 업데이트
binding.resultTextView.text =""
}
equalClicked
fun equalClicked(view : View) {
if(firstNumberText.isEmpty() || secondNumberText.isEmpty() || operatorText.isEmpty()) {
Toast.makeText(this, "올바르지 않은 수식 입니다.", Toast.LENGTH_SHORT).show()
return
}
val firstNumber = firstNumberText.toString().toInt()
val secondNumber = secondNumberText.toString().toInt()
val result = when(operatorText.toString()){
"+" -> firstNumber + secondNumber
"-" -> firstNumber - secondNumber
else -> "잘못된 수식 입니다."
}.toString() // 한 번에 toString() 으로 받기
binding.resultTextView.text = result
updateEquationTextView()
}
operatorClicked
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업데이트함수
// ui 업데이트 함수
private fun updateEquationTextView() {
binding.equationTextView.text = "$firstNumberText $operatorText $secondNumberText"
}
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
class MainActivity : AppCompatActivity() {
private lateinit var binding : ActivityMainBinding
private val firstNumberText = StringBuilder("")
private val secondNumberText = StringBuilder("")
private val operatorText = StringBuilder("")
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().toInt()
val secondNumber = secondNumberText.toString().toInt()
val result = when(operatorText.toString()){
"+" -> firstNumber + secondNumber
"-" -> firstNumber - secondNumber
else -> "잘못된 수식 입니다."
}.toString() // 한 번에 toString() 으로 받기
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() {
binding.equationTextView.text = "$firstNumberText $operatorText $secondNumberText"
}
}