부동소수점 너 뭔데

윤한영·2024년 6월 9일
0

저는 회사에서 회계, 예산 프로그램을 담당하고 있어서 금액을 계산하는 작업이 다수인데

가끔 '분명히 맞는데 왜 이상하게 나오지..?' 싶을 때가 있어서 찾아보다 알게된 내용들입니다!

img

출처: 구글이미지

📒부동소수점과 고정소수점

  • 부동소수점: 좌표 등 약간의 오차가 중요하지 않은 데이터에서 사용

    • 모든 숫자를 1.xxxxxx 형식으로 나타낸다.
    • 첫 번째 비트는 양수, 음수를 구분하는데 사용한다.
    • 그 다음 8비트로 소수점이 몇 칸 움직일 지를 나타낸다. (127과의 차이)
    • 나머지 23자리에 소수점이 움직인 결과에서 소수점 뒤로 오는 부분들을 채워넣는다.
  • 고정소수점: 금액 등 정확한 값이 필요한 경우에 사용

    • bit를 반으로 나눠서 절반은 정수, 절반은 소수 부분에 할당한다.
    • 정수 부분이 큰 숫자, 소수 부분이 정밀한 숫자를 나타낼 수 없다.
    • 정수 부분을 늘리면 소수 부분이 줄어들고, 소수 부분을 늘리면 정수 부분이 줄어들게 된다.

✅ 부동소수점 방식에서 오차가 발생하는 이유

0.1 + 1.1 == 1.2 => false 인 이유

컴퓨터가 숫자를 저장할 때 한 숫자당 32bit의 공간을 마련함

img

출처: https://www.youtube.com/watch?v=-GsrYvZoAdA (코딩애플)

소수를 저장할 때 (IEEE 형식)

  • 첫 번째칸은 음수, 양수 여부
  • 8칸은 정수 부분을 2진법으로 변환해서 저장
  • 나머지 23칸에 소수 부분을 2진법으로 변환해서 저장

일반적으로 0.125와 같은 숫자를 2진수로 변환하면 0.001 과 같이 깔끔하게 딱 떨어져서 변환 가능하지만

0.1 과 같이 깔끔하게 변환되지 않고 0.000110011001001 …. 과 같이 1001이 무한히 이어지는 순환소수가 되는 경우가 있는데

숫자를 저장할 때 32bit를 넘어가면 뒷 부분을 자르고 메모리에 숫자를 저장하게 됩니다.

img

출처: https://www.youtube.com/watch?v=-GsrYvZoAdA (코딩애플)

-> 그래서 자른 부분만큼 오차가 발생함


✅ 해결방법

  1. 소수를 정수로 변환해서 계산
    - 10ⁿ(n=소수점 최대 길이) 만큼 곱해줘서 정수로 만들고, 계산 후 마지막에 다시 10ⁿ만큼 나누는 방법입니다.
    img
  1. decimal.js 라이브러리 사용
	// npm decimal 을 통한 라이브러리 설치

    let number = 0.1;
    let transNumber = new Decimal(number).add(1.1).toString();
    let errorNumber = number + 1.1;
    console.log("> 라이브러리 사용해서 부동소수점 확인 ", transNumber == 1.2);
    console.log("> 일반 연산 부동소수점 확인 ", errorNumber == 1.2);

img

  1. double 자료형 사용 -> 메모리 공간을 2배 차지함(64bit)

0개의 댓글