본문 바로가기

자료구조

코딩 테스트 소수점 출력, 왜 틀릴까? (부동소수점 오차 해결 방법)

SMALL

이 글에서는 소수점 출력 문제부동소수점 오차가 발생하는 이유, 그리고 언어별로 안전하게 정답을 받는 출력 방법까지 한 번에 정리해보겠습니다.

 

 

 

(부동소수점 오차를 설명하는 2진수 변환 구조)

 

1. 컴퓨터는 10진수 소수를 정확히 표현하지 못한다

 
우리는 10진수를 쓰지만, 컴퓨터는 모든 값을 2진수로 저장합니다.
이 차이 때문에 소수점에서 문제가 발생합니다.
예를 들어 0.1을 2진수로 바꾸면 다음과 같습니다.
 

0.00011001100110011... (무한 반복)  -> 2진수로 변환
 

하지만 컴퓨터는 이 값을 끝까지 저장할 수 없기 때문에
중간에서 잘라서 저장하게 되고, 이 과정에서 미세한 오차가 생깁니다.

파이썬으로 확인해보면 바로 드러납니다.

 
print(0.1 + 0.2)
# 0.30000000000000004

#예시 입력:
#0.1 0.2

#예상 출력:
#0.3

#실제 출력:
#0.30000000000000004 (오답)

 

0.3이 아니라 0.30000000000000004가 출력되는데,
이게 바로 부동 소수점 오차입니다.

 

 

 

이처럼 코딩 테스트에서 소수점 출력 문제는 대부분 부동소수점 오차 때문에 발생합니다.
 
 

2. 코딩 테스트의 “오차 허용”에 대한 이해

문제에서 다음과 같은 문구를 주는 이유가 바로 이 부동소수점의 오차 때문입니다!!

정답과의 절대/상대 오차는 1e-6 이하이면 정답으로 인정한다.

 

이건 “완벽한 소수 계산은 어렵다는 걸 아니까, 이 정도 오차는 허용해준다”는 의미입니다.

하지만 출력 형식을 제대로 맞추지 않으면 정답처럼 보임에도 오답이 될 수 있습니다.

 

 

 

3. 가장 안전한 출력 방법 (언어별)

 

 

많은 사람들이 round()를 쓰는데,
코딩 테스트에서는 출력 포맷을 지정하는 방식이 더 안전합니다.

 

ans = 0.1 + 0.2
print(f"{ans:.6f}")

 

python의 경우 .6f를 이용해서 출력 포맷을 지정하고

 

#include <iostream>
#include <iomanip>
using namespace std;

double ans = 0.1 + 0.2;
cout << fixed << setprecision(6) << ans << endl;

 

c++의 경우 iomanip을 include 한후 set precision을 이용해서 출력 포맷을 지정할 수 있습니다.

 

 

 

double ans = 0.1 + 0.2;
System.out.printf("%.6f\n", ans);

 

JAVA의 경우 또한 python과 유사하게 .6f를 활용해서 출력 포맷을 지정합니다.

 

 

4. 실수 문제에서 반드시 지켜야 할 3가지

 

1. 가능하면 정수로 바꿔서 계산하기
소수점 두 자리까지 필요하다면 처음부터 100을 곱해서 정수로 처리하는 게 안전합니다.

사람이 직관적으로 표현할수 있어서 가장 추천드리는 방식입니다!

 

 

2. float 대신 double 사용하기
float은 정밀도가 낮아서 오차가 더 커집니다.

 

 

3. == 비교는 피하기

 

if a == 0.3  # 부동소수점 오류 발생 가능
if abs(a - 0.3) < 1e-9 #오차 범위를 두어 부동소수점 오류 탈출

 

 

글을 마치며

부동 소수점 오차는 코딩을 하다보면 한 번쯤 꼭 겪게 되고, 또 자주 찾게되는 문제입니다.


하지만 이 글로 출력 방식만 제대로 알고 있어도 실수 문제에서 틀릴 일은 거의 사라집니다.

특히 코딩 테스트에서는 이 작은 차이 하나로 정답과 오답이 갈리기 때문에 반드시 익혀두는 것이 중요합니다.

 

괜히 억울하게 틀리는 일 없게, 이 부분은 꼭 암기해서 실전에 적용하면 좋겠습니다.

 

비슷한 문제로 틀려보신 경험 있으면 댓글로 공유해주세요!

 
SMALL