JS에서 문자열이 숫자인지 아닌지 판별하는 방법
개요
► 이 글에서는 JavaScript에서 문자열이 숫자인지 아닌지에 대한 여부를 알 수 있는 방법에 대해 설명한다.
► 프로그래머스 Lv1의 문자열 다루기 기본 문제를 풀며 익힌다.
프로그래머스 문자열 다루기 문제
프로그래머스의 Lv1. 문자열 다루기 기본 문제는 다음과 같다.
문자열 s의 길이가 4 혹은 6이고, 숫자로만 구성돼있는지 확인해주는 함수, solution을 완성하세요. 예를 들어 s가 "a234"이면 False를 리턴하고 "1234"라면 True를 리턴하면 됩니다.
문자열이 모두 숫자로 구성되어있는지 확인하는 문제다. 처음에는 다음과 같이 isNaN()
을 사용한 코드를 짰다.
function solution(s) {
return (s.length === 4 || s.length === 6) && !isNaN(s) ? true : false;
}
당연히 맞아야한다고 생각했으나 정확성 테스트 11번 케이스에서 실패했다. 왜 실패했는지, 그래서 어떻게 풀었는지에 대해 살펴보며 JS에서 문자열이 숫자인지 아닌지 판별하는 방법에 대해 알아보자.
isNaN() 함수에 대하여
isNaN()
함수는 매개변수가 NaN(Not a Number)
인지 판별한다. NaN은 Not a Number의 약자로, 산술 연산이 불가한 경우를 나타낸다. 예를 들어 'b'는 산술연산(덧셈/뺄셈/나눗셈/곱셈 등)을 할 수 없으므로 NaN에 해당한다. 이 말인 즉슨, '3'을 넣으면 false가 나온다는 것이다. 이 점에 유의해야한다. 숫자를 넣으면 false가 나오고 숫자가 아닌 것을 넣으면 true를 반환한다.
NaN에 대해서는 3 === NaN와 같이 논리 연산자를 사용해서는 판별할 수 없다.
console.log(NaN === NaN); // false
따라서 isNaN()
함수를 사용해서 NaN인지 아닌지를 판별해야한다.
isNaN()함수는 매개변수가 Number형이 아닌 경우, 그 값을 먼저 숫자로 강제 변환 시킨다. 내가 지금 'b'를 강제로 숫자로 변환시켜보겠다.
console.log(Number('b')); // NaN
짜잔~ NaN이 나온다. 숫자가 될 수 없는 값을 숫자로 변경시켰기 때문에 나오는 것이다. 그렇다면 '3'을 숫자로 변환시키면 어떻게 될까?
console.log(Number('3')); // 3
너무나 당연하게도 3이 나온다. 이렇듯 숫자로 강제 변환 시켰을 때의 결과값을 평가해서 NaN인지 아닌지에 대해 판단한다. 그렇다면 얘를 이용해서 문자열에 숫자만 포함되어있는지 아닌지를 알 수 있어야 하는 것이 아닌가? 대체 왜 틀린 케이스가 있는 걸까? isNaN에는 특이한 케이스가 많다.
isNaN의 특이한 케이스
1. 공백 문자
'', ' '와 같은 공백은 우리가 생각하기에 당연히 숫자가 아니다. 따라서 isNaN에 넣었을 때 true가 나와야 할 것만 같다.
console.log(isNaN('')); // false
console.log(isNaN(' ')); // false
왜 false 값이 나오는 걸까?
Number(''); // 0
Number(' '); // 0
공백 문자를 Number로 변환하면 0이 나오기 때문이다.
2. 지수 표현
isNaN('1e10') // false
너무나 문자열 그 잡채인데 왜 false가 나오는 것일까?
Number('1e10') // 10000000000
바로 저 친구가 내 재산이었으면 좋겠는.. 큰 숫자를 나타내는 지수 표현이었기 때문이다.
다시 프로그래머스 문제로 돌아가보자.
function solution(s) {
return (s.length === 4 || s.length === 6) && !isNaN(s) ? true : false;
}
우리는 이제 이 코드가 틀렸던, 반례를 찾아낼 수 있다. 바로 방금 전에 했던 '1e10'만 해도 반례에 해당한다.
따라서 좀 더 확실한 비교를 위해 나는 아주 원시적인 방법을 사용해봤다.
function solution(s) {
let flag = true
if (s.length === 4 || s.length === 6) {
for (let i=0; i<s.length; i++) {
if (isNaN(s[i])) {
flag = false
}
}
} else {
flag = false
}
return flag;
}
그냥 냅~다 한 문자 한 문자를 살펴보는 것이다. 이렇게 하니 정답 처리 되었다. 이것은 s가 영문 알파벳 대소문자 또는 0부터 9까지 숫자로 이루어졌다는 제한 사항이 있기에 가능했던 것이고, 만약 공백도 허용되었다면 다른 방법을 써야 했을 것이다. Number(s[i]) != s[i]로 비교하면 될 것 같다.
이렇게 JS에서 문자열이 숫자인지 아닌지 판별하는 방법에 대해서 문제를 풀면서 알아봤다. 자바스크립트를 제대로 공부한지 얼마 되지 않았는데, 자료형 부분에서 헷갈리는 부분이 정말 많은 것 같다.