Search

부동소수점

class
구조
상태
완료
날짜
목차

부동소수점

부동소수점은 실수를 표현하기 위한 방법 중 하나로, 이는 소수점의 위치가 고정되어 있지 않고 "부동"할 수 있기 때문에 이런 이름이 붙었습니다.

부동소수점 수의 구조

1.
부호 : 비트는 수가 양수인지 음수인지를 나타냅니다. 0은 양수를 의미하고, 1은 음수를 의미합니다.
2.
지수 : 이 부분은 소수점의 위치를 결정하며, 수의 크기 또한 결정합니다. 지수는 편향된 형태로 저장되기 때문에 실제 사용 시에는 일정 값(예: 127 또는 1023)을 빼서 실제 지수를 계산합니다.
127은 01111111과 같이 2진수로 표현할 수 있습니다. 지수부의 맨 처음에 0을 쓰고 나머지를 1로 채운 값을 빼는 것이 바이어스 편향입니다. 이를 통해 -127에서 128까지의 지수부를 표현할 수 있습니다.
3.
가수 : 이 부분은 수의 실제 숫자 값을 저장하며, 표준에서는 '1.xxxx...' 형태로 정규화된 가수를 사용하는데, 이 때 가장 앞의 '1'은 대개 저장되지 않고 암시적으로 처리됩니다.

IEEE 754 표준

C#의 floatdouble 타입은 IEEE 754 표준을 따릅니다
float : 32비트
부호: 1비트
지수: 8비트
가수: 23비트
double : 64비트
부호: 1비트
지수: 11비트
가수: 52비트

특수 값 처리

바이어스된 지수 값이 127인 경우 이는 부동소수점 수에서 특별한 경우, 즉 무한대나 NaN을 표현하는 데 사용됩니다.
지수 비트가 모두 1로 설정되고, 가수 비트가 모두 0이면 이는 무한대(Infinity)를 나타냅니다.
지수 비트가 모두 1로 설정되고, 가수 비트가 0이 아니면 이는 NaN을 나타냅니다.

정밀도의 한계

부동소수점 수는 이진 베이스(2진수)를 사용하여 계산되기 때문에, 일부 십진수 값은 정확하게 표현할 수 없습니다. 예를 들어, 0.1 같은 값은 이진 표현에서 정확히 나타낼 수 없어 근사값으로 처리됩니다.
float f1 = 0.1f; float f2 = 0.1f; Debug.Log(f1 + f2 == 0.2f); // False가 나올 수 있음
C#
복사

부동소수점 오류 다루기

이러한 정밀도의 문제를 해결하기 위해 유니티에서는 Mathf.Approximately 함수를 제공하여 두 부동소수점 수가 충분히 가까운지 비교할 수 있습니다.
if (Mathf.Approximately(f1 + f2, 0.2f)) { Debug.Log("Values are approximately equal"); }
C#
복사

Mathf.Approximately의 작동 방식

Mathf.Approximately 함수는 다음과 같은 방식으로 두 수 ab가 거의 같은지를 비교합니다.
public static bool Approximately(float a, float b) { return Mathf.Abs(b - a) < Mathf.Max(1E-06f * Mathf.Max(Mathf.Abs(a), Mathf.Abs(b)), Mathf.Epsilon * 8); }
C#
복사
1E-06f * Mathf.Max(Mathf.Abs(a), Mathf.Abs(b) ): 이 표현은 두 수 중 더 큰 절대값에 0.000001을 곱한 값입니다. 즉, 두 수의 크기에 따라 허용되는 오차 범위가 동적으로 결정됩니다. 두 수가 클수록 더 큰 오차가 허용됩니다.
Mathf.Epsilon * 8: Mathf.Epsilonfloat에서 표현 가능한 가장 작은 값입니다. Mathf.Epsilon의 8배는 극도로 작은 값으로, 이는 매우 작은 값들 사이의 비교에서도 사용될 수 있는 최소한의 오차 한계를 제공합니다.

오차 한계

따라서, Mathf.Approximately의 오차 한계는 두 수의 절대값에 따라 변동되며, 일반적으로는 매우 작은 값 (예: 0.000001배)까지 고려합니다. 이 오차 한계는 부동소수점 연산의 정밀도 한계를 반영하여, 게임 개발 중 작은 차이로 인한 예기치 않은 동작을 방지하기 위해 설계되었습니다.