0.1 + 0.2가 0.30000000000000004인 이유

이진 부동소수점 방식 때문에 0.1과 0.2를 더하면 0.30000000000000004가 나오는 이유와, 이 계산기가 이를 깔끔한 0.3으로 반올림해서 보여주는 원리를 설명합니다.

이진 부동소수점 방식으로 동작하는 계산기라면 거의 어디에서든 0.1 + 0.2를 입력하면 원시 결과값은 0.3이 아니라 0.30000000000000004로 나옵니다. 이 계산기도 내부적으로는 같은 값을 계산하지만, 화면에 표시할 때 반올림하기 때문에 실제로는 0.3이 보입니다. 원인은 진법의 불일치에 있습니다. 사람은 10진법으로 숫자를 쓰지만 컴퓨터는 2진법으로 숫자를 저장하는데, 0.1은 2진법으로 정확히 표현할 수 없는 값이기 때문입니다.

핵심 요약

  • 이진 부동소수점에서는 언어와 상관없이 0.1 + 0.2가 0.30000000000000004입니다.
  • 0.1을 2진수로 나타내면 0.0001100110011…처럼 무한히 반복됩니다.
  • 이 계산기는 결과를 유효숫자 12자리로 반올림하므로, 원시 double 값 대신 0.3이 표시됩니다.
  • 실제로 저장되는 0.1의 값은 0.10000000000000000555111512312578…입니다.

자릿수가 늘어나는 이유

10진법에서 딱 떨어지지 않는 분수가 있다는 것은 이미 알고 계실 겁니다. 3분의 1은 0.333…처럼 무한히 반복되는데, 3이 10의 약수가 아니기 때문입니다. 컴퓨터는 숫자를 2진법으로 저장하는데, 2진법에서 딱 떨어지는 분수는 분모가 2의 거듭제곱인 경우, 즉 2분의 1, 4분의 1, 8분의 1 같은 값뿐입니다. 10분의 1은 여기에 속하지 않습니다. 2진수로 0.1을 표현하면 0.0001100110011…처럼 무한히 반복되는데, 이는 10진수에서 3분의 1이 반복되는 것과 정확히 같은 원리입니다.

배정밀도(double) 숫자는 자릿수를 표현할 수 있는 비트가 53개뿐이라서, 무한히 이어지는 2진 전개가 도중에 잘립니다. 0.1을 입력했을 때 실제로 저장되는 값은 0.1000000000000000055511151231257827021181583404541015625입니다. 이는 0.1에 매우 가깝지만 정확히 같지는 않습니다. 이렇게 미세하게 어긋난 두 값을 더하면 오차가 서로 상쇄되지 않고 누적되어, 합계가 0.3보다 한 단계 더 커지게 됩니다. 그 결과가 바로 0.30000000000000004입니다. 이는 사실상 모든 프로세서와 언어가 구현하는 IEEE 754 표준 때문에 생기는 현상이라, JavaScript, Python, C, 엑셀에서도 동일한 결과가 나타납니다.

이 계산기가 취하는 대응 방식

이 사이트가 따르는 원칙은 부동소수점 연산 가이드에 명시되어 있습니다. 모든 결과는 화면에 표시되기 전에 유효숫자 12자리로 반올림됩니다. double 값은 신뢰할 수 있는 자릿수가 대략 15~17자리인데, 12자리에서 반올림하면 믿을 수 있는 자릿수는 모두 살리고, 누적 오차가 숨어 있는 마지막 몇 자리만 잘라내는 셈입니다.

예제 1: 직접 입력해보기. 메인 계산기에서 0.1+0.2를 입력해 보세요. 화면에는 0.3이 표시됩니다. 실제 내부의 double 값은 0.30000000000000004이지만, 표시 규칙이 이를 감춰줍니다. 반대 방향으로도 같은 현상이 일어납니다. 0.3-0.2를 입력하면 원시 결과는 0.09999999999999998이지만 화면에는 0.1이 표시됩니다. 곱셈에서도 마찬가지입니다. 1.1*3은 내부적으로 3.3000000000000003을 갖지만 3.3으로 표시됩니다.

답을 정확히 확정할 수 없는 경우에는 이 계산기도 억지로 정확한 척하지 않습니다. 1/3을 입력하면 0.333333333333처럼 3이 열두 개 나온 뒤 거기서 멈춥니다. 이런 반올림과 표시 한계가 정확히 어떻게 작동하는지는 유효숫자 가이드에서 자세히 설명합니다.

이 차이가 중요해지는 경우

일상적인 계산이나 숙제, 공학적 어림값 정도라면 유효숫자 12자리는 어떤 측정치보다도 훨씬 높은 정밀도입니다. 다만 다음 세 가지 좁은 상황에서는 이 차이가 실제로 문제가 되며, 자세한 내용은 모두 부동소수점 연산 가이드에서 다룹니다.

  • 금액 계산. 통화를 부동소수점 숫자로 저장하면 안 됩니다. 펜스나 센트 단위를 정수로 다루는 방식이 안전하며, 아주 작은 오차가 누적된 합계는 회계 버그로 흔히 알려진 유형입니다.
  • 코드에서의 동등 비교. 계산된 두 부동소수점 값이 같은지를 직접 비교하는 방식은 신뢰할 수 없으며, 대신 작은 허용 오차(tolerance)를 두고 비교해야 합니다.
  • 긴 연산 체인. 오차가 계속 누적되며, 특히 거의 같은 두 값을 뺄셈할 때 정밀도 손실이 가장 커집니다.

예제 2: 정확한 분수. 정확한 분수 값이 필요하다면 분수 계산기를 사용하세요. 이 계산기는 분자와 분모를 정수 그대로 유지하며 절대 반올림하지 않습니다. 그곳에서 1/3 + 1/3 + 1/3을 입력하면 정확히 1이 나옵니다. 반면 화면에 표시된 소수값으로 같은 계산, 즉 0.333333333333 + 0.333333333333 + 0.333333333333을 해보면 결과는 0.999999999999입니다. 같은 개념이지만 결과는 서로 다른 세계입니다.

예제 3: 제곱근과 제곱. sqrt(2)^2는 대표적인 함정입니다. 논리적으로는 2의 제곱근을 제곱하면 다시 2가 되어야 합니다. 계산기에서 원시 결과는 2.0000000000000004이지만, 화면 표시용으로 반올림되어 2로 나타납니다. 정확한 값이 필요하다면 근호 형태를 그대로 유지하다가 마지막 단계에서 한 번만 계산하는 것이 좋으며, 이 내용은 계산기 함수 참조의 √ 키 항목에서 다룹니다.

알아둘 만한 정수 경계값도 있습니다. 2^53 − 1 = 9,007,199,254,740,991 이하에서는 모든 정수를 정확히 표현할 수 있어 계산기가 모든 자릿수를 그대로 출력합니다. 이 경계를 넘어서면 19!와 같은 값은 존재하지 않는 정밀도를 주장하는 대신 지수 표기법으로 전환됩니다.

자주 묻는 질문

0.1 더하기 0.2는 정말 0.3인가요, 아닌가요?

정확한 10진 연산에서는 0.3이 맞습니다. 하지만 이진 부동소수점에서 실제로 저장되는 결과는 0.30000000000000004입니다. 이 계산기도 내부적으로는 같은 값을 반환하지만, 화면에 표시할 때 유효숫자 12자리로 반올림하기 때문에 0.3으로 보이는 것입니다.

이건 계산기의 버그인가요?

아니요. 이는 사실상 모든 주요 프로세서와 언어가 구현하는 IEEE 754 표준 때문에 생기는 현상입니다. 이런 문제가 없는 것처럼 보이는 프로그램이나 계산기들도 사실은 이 계산기와 마찬가지로 표시 단계에서 반올림해 숨기고 있을 뿐입니다.

정확한 답을 얻으려면 어떻게 해야 하나요?

유리수 연산에는 절대 반올림하지 않는 분수 계산기를 사용하거나, 마지막 단계까지 sqrt(2)나 pi 같은 기호 형태를 수식 안에 그대로 유지하세요.

1을 3으로 나누면 왜 3이 열두 개만 표시되나요?

3분의 1은 10진법에서도 2진법에서도 정확히 표현할 수 없기 때문입니다. 이 계산기는 신뢰할 수 있는 12자리까지만 보여주고, 마치 값이 거기서 끝나는 것처럼 꾸미지 않고 멈춥니다.