인프런 커뮤니티 질문&답변

winwincs님의 프로필 이미지
winwincs

작성한 질문수

Do it! 알고리즘 코딩테스트 with C++

[소수 구하기 실전 문제] 거의 소수 구하기 (백준 1456)

백주 1456번

작성

·

115

0

for (int i = 2; i <= 10000000; i++)

{

if (num[i] != 0)

{

long long temp = num[i];

while ((double)num[i] <= (double)B/(double)temp && (double)num[i] >= (double)A / (double)temp)

{

count++;

temp = temp * num[i];

}

}

}

풀이와 다르게 while 문에서 min값까지 판단하게되면 왜 답이 달라지는건지 모르겠습니다.
어떤 값을 count 못하게 되는건지 모르겠습니다

답변 1

0

안녕하세요, 인프런 AI 인턴입니다.
winwincs님, 질문 주셔서 감사합니다.

코드 내용에 대해 설명드리면, 여기서 num 배열은 소수들을 담고 있는 것으로 추정됩니다. 배열 안의 각 소수에 대해 거듭제곱한 값이 A와 B 사이에 있는지 확인하는 로직으로 보입니다.

while 문의 조건은 num[i]temp로 거듭제곱한 값이 A 이상이고 B 이하일 동안 count를 증가시키는 것입니다. 문제는 num[i]가 실수로 변환되었을 때, 부동소수점 연산의 오차 때문에 정확한 비교가 어려울 수 있다는 점입니다.

min 값까지 판단하면서 답이 달라지는 부분은, 이 부동소수점 연산 오차 때문에 정확한 범위 판단이 이루어지지 않거나, 배정밀도(double)의 한계로 인해 매우 큰 정수 값에 대한 비교가 정확하지 않을 수 있습니다. 그 결과 일부 값을 계산에서 누락하거나 잘못 포함할 수 있습니다.

부동소수점 연산 오차를 줄이기 위해서는 정수 연산을 사용하는 것이 좋은데, 이 경우 while 조건을 다음과 같이 변경할 수 있습니다:

while (temp <= B / num[i] && temp >= A / num[i]) {
    count++;
    temp *= num[i];
}

이렇게 하면 temp 값이 A보다 크거나 같고 B보다 작거나 같을 때까지 반복하며 count를 증가시키게 됩니다. 그럼 필요한 정수의 범위 안에서 정확한 판단이 가능하게 됩니다.

참고로 현재 코드의 temp 값이 매우 커질 경우, 실수로의 변환 과정에서 오차가 발생할 수 있기 때문에 이런 연산 방식을 권장드립니다.

추가적으로, 해당 알고리즘과 코딩테스트에 관한 강의나 자료가 필요하시다면 인프런에서 관련 강의를 찾아보시는 것도 좋을 것입니다.

winwincs님의 프로필 이미지
winwincs

작성한 질문수

질문하기