Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript의 부동 소수점 연산은 항상 100% 정확할까?

JavaScript 부동 소수점 연산의 정확성 문제

JavaScript에서 부동 소수점(floating-point) 연산은 항상 100% 정확하지 않습니다. 예를 들어 1/3을 계산하면 0.33333...처럼 무한히 이어지는 소수가 되는데, 컴퓨터는 이 값을 어느 한 시점에서 반올림하여 저장합니다. 따라서 이렇게 잘린 소수 값끼리 더하면 기대한 결과를 얻지 못하는 상황이 발생합니다.

즉, 두 개의 소수를 더할 때 반올림 오차(rounding error)가 생길 수 있습니다. 다행히 이 오차는 매우 작아서 대부분의 경우 실제 코드 실행 결과에는 큰 영향을 주지 않습니다.

왜 오차가 발생할까?

JavaScript는 모든 숫자를 IEEE 754 표준(64비트 배정밀도 부동 소수점 방식)으로 저장합니다. 이 방식은 2진법 기반이기 때문에 0.1, 0.3처럼 우리에게 익숙한 10진 소수 일부를 정확하게 표현할 수 없습니다. 사람 눈에는 간단해 보이는 소수도 컴퓨터 내부에서는 무한히 긴 2진수로 변환되며, 이 과정에서 미세한 오차가 생기는 것입니다.

예제 1: 0.3 + 0.6

다음 예제에서 0.3과 0.6을 더하면 결과는 당연히 0.9여야 하지만, 반올림 오차 때문에 아래 출력 결과와 같이 기대했던 값이 나오지 않습니다.

<html>
<body>
   <p id="F-P-A"></p>
   <script>
      var err = 0.3 + 0.6;
      document.getElementById("F-P-A").innerHTML = "0.3 + 0.6 = " + err;
   </script>
</body>
</html>

출력 결과

0.3 + 0.6 = 0.8999999999999999

예제 2: 0.2 + 0.1

다음 예제에서 0.2와 0.1을 더하면 의도한 결과는 0.3이지만, 역시 반올림 오차 때문에 기대한 값이 그대로 출력되지 않습니다.

<html>
<body>
   <p id="F-P-A"></p>
   <script>
      var err = 0.2 + 0.1;
      document.getElementById("F-P-A").innerHTML = "0.2 + 0.1 = " + err;
   </script>
</body>
</html>

출력 결과

0.2 + 0.1 = 0.30000000000000004

오차를 피하는 실용적인 방법

금융 계산처럼 정확도가 중요한 작업에서는 다음과 같은 방법으로 오차를 줄일 수 있습니다.

  • toFixed() 메서드를 사용해 소수점 자릿수를 지정하여 반올림합니다. (단, 반환값은 문자열이므로 주의해야 합니다.)
  • 소수를 정수로 변환한 뒤 계산하고, 마지막에 다시 나누어 줍니다. 예: (0.2 * 10 + 0.1 * 10) / 10
  • 정확한 십진수 연산이 필요하다면 decimal.js 같은 전용 라이브러리나 BigInt를 활용합니다.