부동소수점 오차 (Floating-point error)

Dorito·2022년 9월 17일
1

기초공사

목록 보기
2/6

https://velog.io/@dorito/2022.8.20-토요일-공부기록 에서 분리한 내용입니다

부동소수점 오차 (Floating-point error)

참고사이트: https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

유튜브를 보는데 재밌는 영상을 봤다.

console.log(1.1 + 0.1 === 1.2); false 나온다 함

이걸 이해하기 위해서는

컴퓨터는 기본적으로 01010101101010101011100101 .... 을 대책없이 덧셈연산만을 하는 존재라는 것을 알아야한다. (컴퓨터 구조를 알아야 한다) (AND, OR, XOR 연산)

가장 와닿게 알 수 있는 부분이, 마인크래프트에서의 레드스톤이다.

레드스톤은 단순히 스위치로 끄고 켤 수 있는 01만 출력할 수 있는데, 그 레드스톤으로 이런 식으로 구현이 가능하다.


그림 출처

심지어는 레드스톤만으로 1Hz Redstone Computer를 만든 사람도 있다...

https://youtu.be/tDxKhiJfgYk

아무튼!!!! 다시 주제로 돌아와서

컴퓨터가 Float 자료형을 저장하는 법

일단 Floating number는 rational number를 유한개의 수로 나타내기 위한 규약 (예: 파이)이다.

  • 만약 16 bit가 나타낼 수 있는 숫자는 (signed의 경우) -32768 ~ 32767까지 저장 가능하다.

만약 8bit로 5를 나타낸다면 -> (101)
00000101

  • 5.125를 나타낸다면 -> 101.0001(2) float로 나타내는데


(fraction 부분을 mantissa 라고도 한다)

5.125 -> 101.001(2) 으로 바꿔준 후
101 = 1.01 x 10²인 것 처럼
1.01001 x 2²(2) 으로 바꿔준다.

그러면 초록색 영역(Fraction, 23bit)에 소숫점 아래 숫자(01001)를 저장하고, 노란색 영역(Exponent, 8bit)에 지수 2에다 127을 더한 만큼(10000001)을 적어준다.

0.5 (= 1/2), 0.25 (= 1/4), 0.125 (= 1/8) 인 소수 같은 경우에, 2진수로 숫자를 나타내는 컴퓨터는 편안해 하겠지만
10진법으로 0.1은 1/10, 즉 약수 2와 5로 이뤄진 수이기 때문에 부동소수점 산술에서 10 × 0.1이 정확히 1과 같지 않게 만든다. 한마디로 근사치로 계산한다. (수치해석)


자료 출처

숫자를 한없이 정밀하게 표현할 수 있겠지만 숫자 하나에 32bit만큼만 할당하는 float는 오차를 감안하고 범위에 들어온 만큼 자른다.

따라서 부동소수점 오차가 발생하는 것이다.

부동소수점 오차 줄이는 법

  1. 정확히 계산하려면 정수로!
  2. 반올림 문법 사용
  3. double 자료형 사용 (64bit) 메모리 용량 2배 필요
  4. abs(1.1 + 0.1 - 1.2) < EPSILON 로 처리

Case 3번: double 자료형 사용 (64bit) 메모리 용량 2배 필요

정밀도는

  • Single-pricision (32-bit): float in C++
  • Double-precision (64-bit): double in C++

(8bit = 1 byte)

Case 4번: abs(1.1 + 0.1 - 1.2) < EPSILON 로 처리

1/3은 0.3333333... 3으로 무한으로 이어진다고 알지만
무한 소수는 모든 메모리 공간을 쓰고도 표현을 할 수가 없기 때문에
컴퓨터는 어느 순간 마지막 3을 끊고 특정값으로 설정해야 할 필요가 있다.

따라서 특정 시점으로 끊기는 그 수와 수 사이의 간격을 Machine Epsilon(머신 입실론)이라고 한다.
크롬 콘솔창을 열고 Number.EPSILON를 입력해보면
크롬의 자바스크립트 기준으로 머신 입신론 값은 2.220446049250313e-16 가 나온다.

동작 원리만 잘 알고있으면 됨!


자료형 별 나타낼 수 있는 수의 범위~

  • 궁금해서 찾아본 +0 -0 차이

-> Negative zero by IEEE 754 representation in binary32

You can think of zero as a denormalized number (an implicit leading 0 bit) with all 0 fraction bits. Note that −0 and +0 are distinct values, though they both compare as equal.
참고하면 좋을 사이트:
IEEE Standard 754 Floating Point Numbers

위키피디아: Signed zero
https://stackoverflow.com/questions/28949774/what-is-0-0-by-ieee-floating-point-standard

0개의 댓글