본문 바로가기

cs

부동소수점이 발생하는 이유?

부동소수점(Floating-Point Numbers)이란 ?

Floating-Point Numbers
Floating-point numbers are numbers with a fractional component, such as 3.14159, 0.1, and -273.15.
부동소수점이란 위와같이 3.14159, 0.1, and -273.15와 같은 소수구성요소가 있는 숫자를 말한다.

Floating-point types can represent a much wider range of values than integer types, and can store numbers that are much larger or smaller than can be stored in an Int. Swift provides two signed floating-point number types:
부동 소수점 유형은 정수유형보다 훨씬 더 넓은 범위의 값을 나타낼 수 있으며 Int에 저장할 수 있는 것보다 훨 씬 크거나 작은 숫자를 저장할 수 있다. Swift는 두가지 부호 있는 부동 소수점 숫자 유형을 제공한다.

Double represents a 64-bit floating-point number.
Float represents a 32-bit floating-point number.
Double은 64비트 부동 소수점 숫자를 나타내고 Float은 32비트 부동 소수점 숫자를 나타낸다.

  • NOTE
    Double has a precision of at least 15 decimal digits, whereas the precision of Float can be as little as 6 decimal digits. The appropriate floating-point type to use depends on the nature and range of values you need to work with in your code. In situations where either type would be appropriate, Double is preferred.
    Double의 정밀도는 최소 15자리 소수점 이하 자릿수인 반면 Float의 정밀도는 소수점 이하 6자리까지 가능하다. 사용할 적절한 부동 소수점 유형은 코드에서 작업해야하는 값의 특성과 범위에 따라 다르다. 두 유형 중 하나가 적절한 상황에서는 Double이 선호된다.

부동소수점이 발생하는 이유

let sum: Double = 0.1+0.2
print(sum)
// result '0.30000000000000004'
 

내부적으로 컴퓨터는 0.1, 0.2 또는 0.3과 같은 숫자를 정확하게 나타낼 수 없는 형식(이진 부동 소수점)을 사용하기 때문이다.
코드가 컴파일되거나 해석될때 “0.1”은 이미 해당형식에서 가장 가까운 숫자로 반올림되어 계산이 발생하기전에도 작은 반올림 오류가 발생한다.

왜 부동소수점이 필요할까 ?

컴퓨터 메모리는 제한되어 있기때문에 이진 분수를 사용하든 소수를 사용하든 상관없이 무한정 정밀도로 숫자를 저장할 수 없다. 그렇기때문에 어느 지점에서 끊어줘야한다.
그러나
얼마나 많은 정확도가 필요한것일까??
그리고 어디에서 필요할까??
정수의 자릿수와 분수의 자릿수는 몇개인가??

  • 고속도로를 건설하는 엔지니어에게 너비가 10미터인지 10.0001미터인지는 중요하지않다.
  • 마이크로칩을 설계하는 사람에게 0.0001미터(10분의 11밀리미터)는 엄청난 차이이다. 하지만 0.1미터보다 큰거리를 다룰 필요는 없을 것이다.
  • 물리학자는 같은 계산에서 빛의 속도(약 300000000)와 뉴턴의 중력상수를 함께 사용해야한다.

엔지니어와 칩설계자를 만족시키기위해 숫자 형식은 매우 다른 크기의 숫자에 대한 정확도를 제공해야한다.
그러나 상대적 정확도만 필요하다. 물리학자를 만족시키려면 크기가 다른 숫자를 포함하는 계산을 수행할 수 있어야한다.
기본적으로 고정된 수의 정수 및 소수 자릿수를 갖는 것은 유용하지않으며 솔루션은 부동소수점 형식이다.

컴퓨터는 왜 이런시스템을 사용하는걸까 ?

10진수는 1/3과같은 숫자를 정확하게 나타낼수 없으므로 0.33과 같은 값으로 반올림해야 한다. 컴퓨터는 이진수를 처리하는 것이 더 빠르기때문에 이진수를 사용하고 대부분의 계산에서 소수점 이하 17자리의 작은 오류는 전혀 중요하지 않다.

반올림 오류

부동 소수점 숫자는 자릿수가 제한되어 있기때문에 모든 실수를 정확하게 나타낼 수 없다. 형식이 허용하는 것보다 더 많은 자릿수가 있는 경우 남은 자릿수는 생략되고 숫자는 반올림된다.

반올림이 필요한 이유는 크게 세가지가 있다.

  • 유효 숫자가 너무 많을때
    부동 소수점의 가장 큰 장점은 선행 및 후행 0(지수가 제공하는 범위 내)을 저장할 필요가 없다는 것이다. 그러나 그것들 없이 유효 숫자가 저장할 수 있는 것보다 더 많은 숫자가 있으면 반올림이 필요하다. 다시 말해서, 숫자가 단순히 형식이 제공할 수 있는 것보다 더 높은 정밀도를 요구한다면 그 중 일부를 희생해야한다.
  • 주기적 자릿수
    분모가 밑수에서 발생하지 않는 소인수를 갖는 모든 분수는 특정 지점 이후에 주기적으로 반복되는 무한한 수의 자릿수를 필요로 하며 이는 매우 단순한 분수에 대해 이미 발생할 수 있다. 예를 들어, 십진법 1/4에서 2와 5는 10의 소인수이기 때문에 3/5와 8/20은 유한합니다. 그러나 1/3은 유한하지 않으며 2/3, 1/7 또는 5/도 아닙니다. 6, 3과 7은 10의 약수가 아니기 때문입니다. 분모에서 소인수가 5인 분수는 10진법에서는 유한할 수 있지만 2진법에서는 유한하지 않을 수 있습니다.
  • 비합리적 숫자
    비합리적 숫자는 일반 분수로 전혀 나타낼 수 없으며 위치 표기법(기수에 관계 없이)에서는 무한한 숫자의 비반복 자릿수가 필요하다.

0.1 + 0.4와 같은 다른 계산이 올바르게 작동하는 이유는 무엇인가요 ?

이 경우 결과(0.5)는 부동소수점 숫자로 정확히 표시될 수 있으며 입력 숫자의 반올림 오류가 서로를 상쇄할 수 있다.

이문제를 방지하려면 어떻게 해야하나요 ?

어떤 종류의 계산을 하느냐에 따라 다르다.

  • 특히 돈으로 작업할 때 결과를 정확히 합산해야하는 경우: 특수 10진수 데이터 유형을 사용하는 것이 좋다.
  • 추가 소수자릿수를 모두 표시하지않으려면 결과를 표시할때 고정된 소수 자릿수로 반올림한 결과 형식을 지정하면 된다.
  • 사용할 수 있는 10진수 데이터 유형이 없는 경우 대안은 정수로 작업하는 것이다. 그러나 이것은 더많은 작업이 필요하고 몇가지 단점이 존재한다.

Reference