0.1 + 0.2 != 0.3 ??

김지헌·2022년 11월 13일
1
post-thumbnail

[목차]

  • 서론
    - 문제 현상 & 알아야 하는 이유
  • 원인 분석
    - 컴퓨터가 이해하는 언어
  • 해결방안
    - 2가지

[서론]

    const num4 = 0.1 + 0.2;
    console.log(num4);			// 0.30000000000000004 출력
  • 위와 같은 코드를 Visual Studio에서 입력하면 우리의 상식을 벗어난 결과가 출력된다.
  • 저 찌꺼기값은 무시할 수 있을만큼 작아보이지만, 아주 큰 수를 다루거나 정밀한 분야에서는 상당히 치명적인 결과를 초래할 수 있다.

[원인 분석]

  1. 컴퓨터는 신호가 있을 때는 1, 없을 때는 0의 두가지로 모든 것을 표현한다. 따라서 인간이 입력한 10진법의 값을 본인들이 사용하는 2진법으로 바꾼 뒤 계산하게 되는데 이 때 첫번째 문제점이 발생한다.

    "10진법의 유한소수를 2진법으로 바꾸면 무한소수가 나오는 경우가 있다."

    ex)
    0.1(10진법) -> 0.000110011001100...(2진법)


  1. 인간에게 1/3이라는 수를 소수 원래 형태로 표현하는 것(0.333...)은 불가능에 가깝다. 평생을 '3'자 쓰는데에 보낼 수도 없는 노릇이고, 결정적으로 시간이 한정되어있기 때문에 끝을 볼 수 없다. 비슷한 문제가 컴퓨터에게도 적용되는데, 여기서 두번째 문제점이 발생한다.

"컴퓨터의 저장공간은 유한하다"


  1. 컴퓨터는 숫자를 '표준 부동소수점'이라는 방식으로 저장한다.

    • 표준 부동소수점 (=IEEE 754)

      부동소수점
      = 浮: 뜰 부, 動: 움직일 동

      즉, 소수점의 위치를 옮겨서 숫자를 표현하는 방식

    이 때 주로 32bit의 유한한 공간에 저장을 하게 되고, 위의 예시에 해당하는 0.1(10진법)은 아래와 같이 표현된다.

	0.0001100110011 ...	
		1.100110011 ...
    
	0 0111101 11001100 11001100 11001101
    - ---------                        -

따라서 이렇게 오차가 생길 수 밖에 없게 되고, 제목의 상황처럼 10진법으로 계산했을 때는 깔끔하게 떨어져야할 값이 부정확해지는 것이다.


[해결방안]

  1. 실수 범위에서 계산할 때 나타나는 문제이므로 가급적 정수로 고쳐서 표현하자.

    ex)

  const num5 = (1 + 2)/10;
  console.log(num5);			// 0.3 출력

-> 위와 같이 각 숫자를 정수로 고친 뒤 계산을 하게되면 오류가 발생하는 것을 막을 수 있다.


  1. 오차를 줄이기 위해 float보다는 double을 사용하자.

float은 7자리, double은 15~16자리 까지 표현할 수 있습니다.


  1. 각 언어마다 제공하는 정확한 실수 계산을 위한 라이브러리들을 사용한다.

    JavaJavaScriptPython
    BigDecimalbig.jsdecimal 모듈

-> 기본 자료형의 한계를 소프트웨어적으로 보완해준다.


  1. toFixed()함수, Math.round(), Math.floor(), Math.ceil(), Math.trunc()
    등의 함수 사용하기
profile
Still Dreaming..

0개의 댓글