백준 사이트를 통해 배운 NumberFormat 런타임 에러

Bruce Han·2022년 12월 26일
0

Java 튜토리얼

목록 보기
2/3
post-thumbnail

이 문제를 10진수로 1000의 자리를 넘지 않는다길래 1001, 1002, ... 의 숫자를 다루겠거니 해서 int로 변수의 타입을 정해서 풀려고 했지만 쉽게 풀리지 않았다.
알고보니 1000제곱을 했을 때의 값을 얘기하는 거였다. 10의 자리수, 100의 자리수를 얘기하는게 아니었다.

주로 접했던 오류는 NumberFormat 런타임 에러이다.
백준 온라인 저지 사이트에서는 NumberFormat 런타임 에러를 어떻게 다루고 있을까?

java.lang.NumberFormatException은 문자열을 수로 변환할 때 발생하는 에러입니다.

다음 소스는 int범위의 정수 두 개를 입력받은 후 더한 값을 출력하는 소스이다.

/* 소스 1 */
import java.util.*;
import java.io.*;
class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        int a = Integer.parseInt(bf.readLine());
        int b = Integer.parseInt(bf.readLine());
        System.out.println(a+b);
    }
}

위 소스가 올바르게 동작하려면, 첫째 줄과 둘째 줄에 수가 각각 하나씩 있어야 한다. 따라서, 입력이 다음과 같은 경우에는 올바르게 7을 출력하게 된다.

3
4

하지만, 입력이 다음과 같은 경우에는 java.lang.NumberFormatException이 발생한다.

3 4

이때 발생하는 런타임 에러는 다음과 같다.

Exception in thread "main" java.lang.NumberFormatException: For input string: "3 4"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at Main.main(Main.java:7)

문자열 "3 4"는 정수 하나로 변환할 수 없기 때문에(3과 공백 한 칸과 4), 에러가 발생하는 것이다. 이런 경우에는 소스가 문제의 입력 형식을 잘 지키고 있는지 확인해봐야 한다. 입력이 한 줄에 공백으로 구분되어서 들어오는 경우, BufferedReader를 이용해 올바르게 구현한다면 다음과 같다.

/* 소스 2 */
import java.util.*;
import java.io.*;
class Main {
	public static void main(String[] args) throws IOException {
    	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] strArr = br.readLine().split(" ");
        int a = Integer.parseInt(strArr[0]);
        int b = Integer.parseInt(strArr[1]);
        System.out.println(a+b);
    }
}

java.lang.NumberFormatException은 수가 자료형의 범위를 벗어나 해당 자료형으로 벗어날 수 없을 때도 발생한다.

소스 1에 다음과 같은 입력을 넣으면 런타임 에러가 발생하고, 그때 메시지는 다음과 같다.
긴자리 계산 문제에서 주어진 입력에도 들어갈 수 있는 숫자이다.

21000
31000

Exception in thread "main" java.lang.NumberFormatException: For input string: "123456789123"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:583)
at java.lang.Integer.parseInt(Integer.java:615)
at Main.main(Main.java:7)

소스 1은 Integer.parseInt를 사용하고 있기 때문에, 결과가 Integer의 범위 안에 들어있어야 한다. 21000과 31000은 231-1보다 커서 Integer의 범위를 벗어나기 때문에, java.lang.NumberFormatException이 발생한다.

이런 경우에는 문제의 입력 조건에 해당하는 자료형을 사용하고 있는지 살펴봐야 한다.

참고로 엄청 큰 수를 다룰 때에는 BigInteger 자료형을 사용해야 할 것이다. BigInteger 자료형은 소스 1처럼 '+'기호로 더하지 않고 'add(BigInteger val)'로 더해야 한다.

// Not a + b
a.add(b); // BigInteger 형의 객체를 생성한 후 메서드를 불러올 것

문자열에 숫자가 아닌 문자가 들어있는 경우에도 이 에러가 발생한다. 소스 1의 입력이 다음과 같다면 런타임 에러가 발생한다.

2b5
9876

Exception in thread "main" java.lang.NumberFormatException: For input string: "1a2"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at Main.main(Main.java:7)

가장 처음에 설명한 "3 4"의 예시가 여기에 해당된다고 볼 수 있다. 이유는 공백 한 칸이 숫자가 아닌 문자이기 때문이다.

입력받을 것이 없는데, 입력을 받는 경우에도 이 에러가 발생한다. 소스 1에 다음과 같이 정수 하나만 입력으로 들어온다면, 8번 줄의 br.readLine()는 null을 리턴한다.

7

따라서, 8번 줄은 int b = Integer.parseInt(null);과 같은 의미를 가지며, null은 Integer로 변환할 수 없기 때문에 런타임 에러가 발생한다. 런타임 에러 메시지는 다음과 같다.

Exception in thread "main" java.lang.NumberFormatException: null
at java.lang.Integer.parseInt(Integer.java:542)
at java.lang.Integer.parseInt(Integer.java:615)
at Main.main(Main.java:8)

Reference

profile
만 가지 발차기를 한 번씩 연습하는 사람은 두렵지 않다. 내가 두려워 하는 사람은 한 가지 발차기를 만 번씩 연습하는 사람이다. - Bruce Lee

0개의 댓글