정수 제곱 판별

나의 기록·2026년 6월 2일

코딩테스트

목록 보기
7/35

문제

임의의 양의 정수 n에 대해, n이 어떤 양의 정수 x의 제곱인지 아닌지 판단합니다.

  • n이 양의 정수 x의 제곱이라면 (x+1)² 리턴
  • n이 양의 정수 x의 제곱이 아니라면 -1 리턴

풀이 과정

핵심 아이디어

  1. Math.sqrt(n) 으로 제곱근을 구한다
  2. 제곱근이 정수인지 확인한다
  3. 정수라면 (x+1)² 리턴, 아니라면 -1 리턴

리팩토링 전

long answer = 0;

double sqrtNum = Math.sqrt(n);

if (sqrtNum % 1 == 0) {
    double number = Math.pow(sqrtNum + 1, 2);
    answer = Math.round(number);
} else {
    answer = -1;
}

System.out.println(answer);
return answer;

문제점

  • double 타입으로 % 1 == 0 비교 시 부동소수점 오차 발생 가능
    • ex) Math.sqrt(어떤 큰 수)2.9999999... 처럼 나올 수 있음
  • Math.pow(), Math.round() 불필요하게 사용

리팩토링 후

long answer = 0;

int sqrtNum = (int) Math.sqrt(n);

if ((sqrtNum * sqrtNum) == n) {
    sqrtNum++;
    answer = sqrtNum * sqrtNum;
} else {
    answer = -1;
}

System.out.println(answer);
return answer;

개선된 점

  • (int) 캐스팅으로 소수점을 버린 후, 다시 제곱해서 n 과 비교
  • double 비교 없이 정수끼리 비교 → 부동소수점 오차 없음
  • 불필요한 Math.pow(), Math.round() 제거

배운 점

부동소수점 오차 처리

double 타입은 정밀도 문제로 비교 시 오차가 생길 수 있다.
정수 판별이 목적이라면 (int) 캐스팅 후 재계산해서 비교하는 것이 안전하다.

// ❌ 위험
double sqrtNum = Math.sqrt(n);
if (sqrtNum % 1 == 0) { ... }

// ✅ 안전
int sqrtNum = (int) Math.sqrt(n);
if (sqrtNum * sqrtNum == n) { ... }

증가 연산자

sqrtNum = sqrtNum + 1; // 가능
sqrtNum += 1;          // 가능
sqrtNum++;             // 가장 관용적인 표현 ✅

Math.round() 반환타입

Math.round(double) 의 반환타입은 long 이다.
리팩토링 전 코드에서 answer(long) 에 바로 대입이 가능했던 이유!

long answer = Math.round(3.7); // 반환타입 long → 대입 가능
profile
뭐든 남겨본다

0개의 댓글