csapp 2.4다
여긴 real jot이니
집중하자
정수도 jot인데
소수는 big jot인건 상식
부동산…
움직이지 않는 자산이란 뜻이다
그리고 부동소수점은
움직이는 소수점이란 뜻이다…
$농담아니다$ (궁서체)
아닐 부(不) 가 아닌
뜰 부(浮) 다 ㅅㅂ
움직이지 않는게 아닌 “떠서” 움직여서
부동소수(float)이다
부동소수점은 수를 각각 $V=xw^y$ 의 형태로 표시한다
당연하다면 당연하게도 모든 수를 다 표시하진 못한다
애시당초 정밀도 보단 속도와 편의성에 투자헀으니 오차값 찐빠가 난다
그리고…
지금까지 사용하는 표준 부동소수점은
IEEE 표준 754 방식이다
I *triple 표준 754라고 말하며 멋들어지게 꺼드럭대보자
수를 $2^i$의 합으로 표현한다는 뜻2다
2진수의 소수는 2로 표현한다
그게 뭔소리냐…
예시) $[10.111] = 2^2 + 2^{-1} + 2^{-2} + 2^{-3}$
이렇게 쓴다는 말(horse라는 mean아님)이다
IEEE 표준은 수를 $V = (-1)^s * M * 2^E$ 의 형태로 나타낸다
ㅅㅂ 또 jot같은 공식이네하고 넘기지 말아라
설명해주겠다
s는 음양을 표현한다
0이면 양수 1이면 음수…
그게 끝이다
존나 간단하니 더 설명 안하겠다
그럼 +0, -0 생기는 거 아니냐?
할 수 있는데 이건 뒤에서 설명하겠다
__
E는 예시부터 보자
예시)
0.0001100110011001
(2진법) = 1.100110011001
* $2^{-4}$
쉬프팅 덕에 이리 연산 가능하다는 건 알거다
소숫점을 옮긴만큼이 E다. 예시에선 -4가 E이다
M은 1.xxx에서 xxx를 담당한다
__
IEEE 표준 754에선
맨앞 부호 담당 비트를 s,
M의 담당 비트를 n,
E의 담당 비트를 e라고 정했다
크기도 정했는데
float (32bit) 에선 s = 1bit, e = 8bit, n =23bit
double (64bit) 에선 s = 1bit, e = 11bit, n =52bit
로 정했다
그리고 IEEE표준에선 3가지 케이스로 비트를 해석한다
기준은…
지수필드다
지수필드는 e나 E를 의미한다
아무튼 지수필드가 전부 0일때, 1일때, 그 외로 나뉜다
에지간해선 그 외일 거다
이를 정규화(Normalized)라 한다
이름보명 알 수 있듯이 normal(평범이라는 뜻)한 상황이다
지수필드의 경우 비부호로 표기한다
크기 비교 등 비부호가 더 간단하고 유용하니 말이다
전부 0일 떄와 전부 1일때인 255를 제외하면
1~254가 E가 있을 수 있는 범위다
원래라면 -128 ~ 127을 값을 가질 수 있는 E에
127을 더해 1 ~ 254로 바꿔준거다
여기선 127이 bias(보정값이라는 뜻)가 된다
아무튼 E를 어따가 쓰냐면
$0.0001100110011001$ (2) => $1.100110011001 * 2^{-4}$
-4가 E
e= E+127 = 123 이고 [01111011]로 표현가능하다
___
이번엔 M에 대해 알아보다
얜 가수(singer아님) 필드라고 부른다
1.xx...
라고 표현할때 .xx...
부분이다
1.xx...
을 M, xx...
부분을 보통 f라고 부른다
여기서 고대 프로그래머들의 티끌 모으기를 볼 수 있다
1.xx...
가 되게 쉬프팅을 했기에
0.xx...
일 때는 고려를 안해 1을 표현하는 비트를 안 써
무려 비트 하나를 아낄 수 있다
비트 하나하나 알차게 써먹된 고대 프로그래머들의 절약 정신을 느낄 수 있다…
여기까지 짠내가 나는 기분이고 말이다
__
그렇게 소수를 비트 배열로 인코딩 시 결과는
s(1)eeeeeeee(8)fffffffffffffffffffffff(23)
이렇게 된다
위에 있는 수로 또 예시를 들자면
0/01111011/10011001100100000000000 = 0x3DCCC800
라는 거다
__
e가 전부 0일때 이를 비정규화(denormalized)라고 한다
이때에는 $1.xx * 2{^-127}$ 이 아니라 $0.xx * 2{^-126}$라고 한다
왜 ㅅㅂ 라고 묻는다면
이렇게 하는게 더 범위를 넓게 쓸 수 있으니 말이다
전자를 쓰게 되면 최솟값이 $2^{-127}+2^{-150}$
후자를 선택하면 최솟값이 $2^{-149}$가 되어 더 작은 수 까지 표현 가능하다
(개구리가 따봉하는 그림)
이제 여기서 왜 +0
, -0
이 용인되는지 알려주겠다
정수 타입에선 0
2개를 막기 위해 염병을 하던 것과 달리
용인되는 이유는…
그야 의도되었으니까
$lim→0$ 같은 느낌이다
+0
으로 수렴할떄랑 -0
으로 수렴할때를 나누기 위해서 말이다
___
e가 모두 1일때, 이를 특수 값이라고 표현
ㄹㅇ 말그대로 특수 값이라는 뜻으로
f가 전부 0이면 infinity취급하고
f가 0이 아니면 Nan(Not a Number)을 나타낸다
숫자로 취급하지는 않고 에러 출저나 다른 데이터 담을 때 사용한다
루트 -1이라 무한대 - 무한대 등 계산하면 리턴된다
여기선 우리가 다룰 수 있을만큼 숫자를 낮추어 예제를 다뤄보겠다
구분 | 비트 배열 | 지수 필드 (e, E, 2^E) | 가수 필드 (f, M) | 값 (2^E × M), V | 10진수 값 |
---|---|---|---|---|---|
0 (제로) | 0 0000 000 | 0, -6, 1/64 | 0/8, 0/8 | 0/512, 0 | 0.0 |
비정규화 최소값 | 0 0000 001 | 0, -6, 1/64 | 1/8, 1/8 | 1/512 | 0.001953 |
비정규화 최대값 | 0 0000 111 | 0, -6, 1/64 | 7/8, 7/8 | 7/512 | 0.013672 |
정규화 최소값 | 0 0001 000 | 1, -6, 1/64 | 0, 8/8 (M=1) | 8/512, 1/64 | 0.015625 |
정규화 값(1) | 0 0111 000 | 7, 0, 1 | 0/8, 8/8 (M=1) | 1 | 1.0 |
정규화 최대값 | 0 1110 111 | 14, 7, 128 | 7/8, 15/8 | 240 | 240.0 |
무한대 | 0 1111 000 | - | - | - | ∞ |
e
부분이 모두 0가수(M) = f/8
2^(-6) × (f/8)
(여기서 -6은 bias 적용된 최소 지수)e
부분이 1도 아니고 0도 아님가수(M) = 1 + f/8
2^(E) × (1 + f/8)
e
부분이 전부 1, f
는 0참고: 정규화 값에서 e의 bias를 적용해 실제 지수(E)를 계산
예시에서 bias는 2⁽ᵉ⁻¹⁾-1 = 7.
예를 들어, 정수
00000000000000000011000000111001
을 부동소수점으로 변환하면,
10001100
100000011100100000000000000
최종 부동소수점 비트 배열:
0 / 10001100 / 100000011100100000000000000
Note: f 부분이 정수와 겹치는 구조임을 알 수 있다
당연하게도 모든 소수를 다루는 건 존나 무리다
그렇기에 우린 근사를 때린다
근사법은 네가지 방법이 있는데 한가지만 기억하면 된다
물론, 그 한가지가 좀 까다롭다
짝수근사법, 0방향근사법, 상향근사법, 하향근사법 4가지가 있다
하향근사법은 무조건 버림이다
ex) 1.6->1 / -1.5->-1
상향근사법은 무조건 올림이다
ex) 1.3->2 / -1.5->-1
0방향 근사법은 걍 소숫점 때면 된다
ex) 1.6->1 / -1.5->-1
마지막으로 짝수 근사법이다
부호 상관없이 중간 값이 짝수가 되도록 근사하는 방법인데…
말로하기 어려우니 예제와 함께 설명하겠다
01010001100100
같이 비트가 주어지고
01010001100/100
을 /
로 나눈 떄까지만 보려 할때
/
아래 값이 100
이면 중간값이라 한다
100
앞에 수가 1이면 +1, 아니면 버리면 된다
지금은 0100
이니 걍 버려버리면 된다
부동소수점의 덧셈과 곱셈의 방법은 나오지 않는다
대신 교환법칙등 특성만 서술한다
일단, 교환법칙이 성립한다
ex) x+y = y+x
하지만, 결합법칙은 성립하지 않는다
이유는 근사 때문이다
$3.14+1e10-1e10$ 이라고 할때 ($1e10$은 $10^{10}$)
$(3.14+1e10)-1e10 = 1e10-1e10$ = 0이 나온다.
그치만…
$3.14+(1e10-1e10)=3.14$
가 쳐 나와버린다
그러니 결합법칙은 주의하자
반면에 단조 특성이란 건 갖고 있다
$a >= b$이면
$a + c >= b + c$라는거다
웃긴건 정수는 오버플로우 때문에 단조성이 없다
부동소숫점의 곱셈
곱셈이 닫혀있다고 표현하는데
적절한 소수, 무한대, NaN중 하나로 값이 결정된다는 소리다
덧셈이랑 똑같이 교환법칙 성립하고 결합법칙 성립안하고 단조성 존재한다
똑같이 정수는 단조성 없다
c에선 float과 double을 지원한다
그리고… 근사 할때 짝수 근사모드! 를 사용한다
그리고 타입 변환시 변경점이 적혀 있다
int -> float : 숫자가 근사된다
int, float -> double : 정확하게 보존된다
double -> float : 오버플로우 되서 무한되거나 근사된다
수가 너무 크거나 정수 표현 힘들면 에러라는 뜻으로 Tmin을 반환하기도 한다
컴퓨터는 정보를 비트로 인코딩하고 이를 연속된 바이트로 구성한다.
___