반지름을 나타내는 두 정수 r1, r2가 매개변수로 주어질 때, 두 원 사이의 공간에 x좌표와 y좌표가 모두 정수인 점의 개수를 구하는 문제
import java.util.*;
class Solution {
public long solution(int r1, int r2) {
long answer = 0;
answer += (long)(r2 - r1 + 1) * 4;
for(int i=1; i<r2; i++){
long tmp1 = (long)Math.pow(r2,2);
long tmp2 = (long)Math.pow(i,2);
long top = (long)Math.floor(Math.sqrt(tmp1 - tmp2));
answer += top * 4;
}
for(int i=1; i<r1; i++){
long tmp1 = (long)Math.pow(r1,2);
long tmp2 = (long)Math.pow(i,2);
long top = (long)Math.ceil(Math.sqrt(tmp1 - tmp2)) - 1;
answer -= top * 4;
}
return answer;
}
}
구현 자체는 어렵지 않았다. 큰 원 안에 있는 정수쌍의 개수에서 작은 원 안에 있는 정수쌍의 개수를 빼면 되는 문제.(15줄로 푼 분도 계시는데 매커니즘 자체는 비슷하다.)
문제는 long 타입을 사용하는거였다. 뒷번호 테스트케이스만 통과되지 않을 때 타입 문제라고 생각을 했는데, 어디서 문제가 발생한건지 찾는게 어려웠다.
문제의 원인은
long tmp1 = r2 * r2;
여기서 발생했다.
int형인 r2를 곱하면 int로 담기에는 오버플로우가 생겨 long타입으로 받으면 괜찮을 줄 알았지만 java에서 int * int 는 int 범위 내에서 계산이 되기 때문에 tmp1으로 넘겨주기 전에 이미 오버플로우가 발생한다....!!
그래서 코드를
long tmp1 = (long)r2 * r2;
또는
long tmp1 = (long)Math.pow(r1,2);
이렇게 바꿔야한다...
(참고로 pow는 결과가 double로 계산된다.)
항상 long타입이 나올 때 이러한 오버플로우 문제로 어려움을 자주 겪는 것 같다.
int * int는 int 범위에서 계산되는걸 꼭 기억하자....!