일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- gradle
- Set
- Java
- sonarQube
- Linux
- post
- DevOps
- 액세스회선
- mybatis
- 소켓
- docker
- ansible
- tomcat
- map
- cloud
- JPA
- STREAM
- jdk
- Collection
- 방화벽
- LAN어댑터
- AOP
- container
- 허브
- Spring
- 라우터
- 캐시서버
- Jenkins
- Pipeline
- IntelliJ
- Today
- Total
거북이-https://velog.io/@violet_evgadn 이전완료
Long & Int 범위 본문
코딩 테스트 시 필요한 이유
Java로 코딩 테스트를 준비하다 보면 분명 로직이 정확한 것 같은데 답이 틀리는 경우가 있다.
심지어 반 이상은 맞는 상황이 다수인지라 더욱 미쳐버릴 것 같다.
이런 경우 10번 중 7-8번은 Int와 Long의 범위 차이 때문에 생기는 에러였다.
코딩 테스트에서 int형 데이터로 Input이 들어오고 Output 또한 int형 데이터라면 대부분 형 변환을 수행하지 않고 코딩한다.
하지만 (int 데이터) * (int 데이터)의 결과가 int 범위를 넘어가는 경우가 존재한다.
이 경우 Overflow 문제가 발생하는데 Java는 이 상황에서 에러를 발생시키는 것이 아닌 이상한 중간 결과를 반환한다.
당연히 중간 연산 결과가 틀리니 답 또한 제대로 반환되지 않는 것이다.
이유는 프로그래밍 언어가 이진법을 사용하기 때문인데, 간단히 설명하자면 Signed 자료형은 가장 앞자리 Bit를 Sign Bit로 지정한다. 이 Sign Bit가 1이면 음수, 0이면 양수로 지정하는데 Overflow 문제가 발생하면 대부분 Sign Bit가 1이 되므로 양수 * 양수를 했는데 결과는 음수가 나오는 상황이 발생하는 것이다.
또한 Bit 수를 넘기는 결과는 메모리 상에서 없어지므로 Overflow 문제 발생 시 제대로 된 연산 결과가 나오지 않는 것이다.
따라서 이런 문제를 피하기 위해 Long과 Int 범위를 미리 파악하는 것이 좋다고 생각했다.
int
int는 데이터를 표현하기 위해 총 4 Byte 공간을 활용한다.
1 Byte = 8Bit이므로 int형 데이터는 총 32 Bit만큼을 데이터를 표현하는데 활용하는 것이다.
가장 앞쪽의 Bit는 Sign Bit(양수, 음수를 구분하는 Bit)이므로 int형 데이터는 -2³¹ ~ 2³¹까지 표현할 수 있게 된다.
코드를 통해 확인해 보자.
int intMax = Integer.MAX_VALUE;
int check = (int) Math.pow(2, 31);
System.out.println(intMax==check);
True. 즉 Integer의 Max Value와 2³¹은 같다는 것을 알 수 있다.(최솟값도 궁금하면 Integer.MIN_VALUE로 테스트해 보자)
여기에서 중요한 것이 int형 범위를 10의 거듭제곱으로도 알고 있어야 한다.
실제로 코딩 테스트 문제에서 값의 최소 및 최댓값을 2의 거듭제곱으로 알려주는 것보다 10의 거듭제곱으로 알려주는 경우가 더 많다.
답부터 말하자면 int형 데이터는 -10⁹ ~ 10⁹의 데이터를 표현할 수 있다.
(정확히는 -9.xxx이지만 소수 값까지 외울 필요는 없다.)
10ⁿ = 2³¹이므로 n = 31log2임을 알 수 있다.
log2는 약 0.301이므로 n은 9.3xxx값을 가질 것이다. 즉, int형 데이터는 -10⁹ ~ 10⁹의 데이터를 표현할 수 있음을 알 수 있는 것이다.
long
long은 총 8 Byte를 활용한다.
즉, long은 수를 표현하기 위하여 총 64 Bit 공간을 활용하는 것이다.
long형 데이터는 -2⁶³ ~ 2⁶³의 범위를 가진다.
long intMax = Long.MIN_VALUE;
long check = (long) -Math.pow(2, 63);
System.out.println(intMax==check);
10의 거듭제곱으로 표현하자면 -10¹⁸ ~ 10¹⁸의 범위를 가지는 것이다.
(10ⁿ = 2⁶³ 이므로 n = 63log2 = 18.xxx 이므로 -10¹⁸ ~ 10¹⁸ 범위임을 알 수 있다)
범위 정리
- int
- -2³¹ ~ 2³¹
- -10⁹ ~ 10⁹
- long
- -2⁶³ ~ 2⁶³
- -10¹⁸ ~ 10¹⁸
추가 설명
코딩을 완료했으면 먼저 모든 곱 연산을 살펴보자.
곱 연산에 Input의 최댓값을 집어넣어 결과물을 도출했을 때 int형 범위를 넘어간다면 그냥 곱하기가 존재하는 모든 상황에서 long 형으로 형변환을 수행한 후 연산을 진행하자.
(int형 데이터를 long 형 데이터로 변환할 때는 Overflow 문제가 발생하지 않는다. 반대의 경우에는 문제 발생 가능성 존재)
특히 거듭제곱 연산이 필요한 경우 웬만하면 Math.pow()를 통해 거듭제곱 연산을 진행한 후 long형으로 형 변환을 진행하도록 하자.
'코딩 테스트 시 알면 좋은 것들' 카테고리의 다른 글
문자열 뒤집기 (0) | 2023.01.03 |
---|---|
Compare 관련 메소드 (0) | 2022.12.31 |
log & 거듭제곱 (0) | 2022.12.30 |
N 진법 (0) | 2022.12.30 |
Stream을 활용한 Collection to Array & Array to Collection (0) | 2022.12.30 |