• 소수점 이하를 표현하는 방법
고정소수점(Fixed-Point)
소수점 위치가 고정되어 있다.
1101101.00010001
Integer(정수).Fractional(소수)
특정 비트수를 기준으로 소수점이 찍힌 것을 알 수 있다.
부동소수점(Floating-Point)
1.1011010001001 * 2⁶
1(leading 1)의 오른쪽에 소수점이 위치하고, Exponent가 사용된 것을 알 수 있다.
• 고정소수점
정수부 4비트, 소수부 3비트를 사용하는 고정소수점 표현
0110110
0110.110
= 2² + 2¹ + 2⁻¹ + 2⁻² = 6.75
Binary point는 비트표현에 들어가는 것이 아닌, 일종의 약속이다.
음수 소수는 두가지 방법으로 표현할 수 있다.
1. 부호/크기 표현법
2. 2의 보수 표현법
8비트 바이너리 표현을 사용해서 -7.5₁₀를 표현해보자.
7.5
= 7 + 0.5
= 4 + 2 + 1 + 0.5
= 2² + 2¹ + 2⁰ + 2⁻¹
= 0111.1000
부호/크기 표현법을 사용하면 7.5 ₁₀ 가 음수이므로 맨 앞의 0을 1로 바꿔주어야 한다.
11111000
2의 보수 표현법을 사용하면(보수 취하고 +1) 아래와 같다.
하지만 고정소수점을 사용하면 비트로 표현할 수 있는 수의 범위가 한정되는 문제가 있다.
• 부동소수점
부동소수점의 소수점은 가장 큰 숫자 바로 오른쪽에 위치한다.
273₁₀ = 2.73 * 10²
따라서 일반화를 진행하면, ± M * B^E가 된다.
M = maintissa
B = base
E = exponent
M = 2.73, B = 10, and E = 2
• 부동소수점을 표현하는 3가지 방법
방법 1
228₁₀ = 11100100₂ = 1.1100100 * 2⁷
양수이므로 sign bit는 0이다.
8 exponent bit는 2의 지수인 7이다.
남아있는 23 bit는 mantissa이다.
방법 2
mantissa의 첫번째 비트는 항상 1이다.
228₁₀ = 11100100₂ = 1.11001 * 2⁷
171₁₀ = 10101011₂ = 1.0101011 * 2⁷
17₁₀ = 100001₂ = 1.00001 * 2⁴
따라서 어떤 숫자를 바꾸더라도, ± M * B^E 표현으로 바꾸면, 1.xxx로 1이 항상 존재한다.
그래서 우리는 1.xxx의 1을 저장하는 대신에, 항상 있다고 가정하자.
방법 3(IEEE 754)
연산을 용이하게 하기 위해 Bias 개념을 도입한다.
Bias 공식 = 2^n-1 -1
8bit에서 사용
2^8-1 = 127
따라서 8 bit에서는 Bias가 127₁₀ = 01111111₂이 될 것이다.
(11bit에서는 1023₁₀)
방법 1이나 2와 다르게 Exponent가 아닌 Biased Exponent로 들어가게 되는데,
Biased Exponent = bias + exponent이므로
Biased Exponent는 127(bias) + 7(exponent)의 값인 134 = 100000110₂가 된다.
-58.25₁₀을 IEEE 75를 사용해 32bit 부동소수점 계산을 해보자.
-58.25₁₀ = 111010.01₂ = 1.1101001₂ * 2⁵
Sign bit : 1(음수)
8 exponent bit : 127(8 bit) + 5 = 132₁₀ = 10000100₂
23 fraction bit : (1)1101001... (1은 음수로 인한 sign 값이므로 제외)
C언어에서는 어떻게 표현되는지 알아보자.
이를 통해 아주 정밀한 계산이 아닌 경우 float가 더 유리하다는 것을 알 수 있다.
• 라운딩
숫자가 너무 클 때는 Overflow, 너무 작을 때는 Underflow가 일어난다.
따라서 여러가지 라운딩 방법이 있다.
- Down(내림)
- Up (올림)
- Toward zero (0에 가깝게)
- To nearest (가장 가까운 수로)
각각의 값이 달라지는 것을 확인할 수 있다.
• 부동소수점 덧셈
부동소수점 연산은 다음과 같은 순서로 진행된다.
1. Exponent와 Fraction bit를 추출한다.
2. mantissa를 1.xxx의 형태로 변환한다.
3. Exponent를 비교한다.
4. 작은 mantissa를 shift 한다.
5. mantissa끼리 덧셈한다.
6. 필요시 mantissa를 정규화한다.
7. 결과를 라운딩한다.
8. Exponent와 Fraction을 부동소수점 형태로 바꿔준다.
Step1
N1 : S = 0, E = 127, F = .1
N2 : S = 0, E = 128, F = .101
Step2
N1 : 1.1
N2 : 1.101
Step3
127 - 128 = -1
Step4
N1을 1 bit 만큼 오른쪽으로 이동
1.1 >> 1 = 0.11 (* 2¹)
Step5
0.11 * 2¹
+ 1.101 * 2¹
= 10.011 * 2¹(필요에 따라 carry 진행)
Step6
10.011 * 2¹ = 1.0011 * 2²
• 정규화된 수 vs 비정규화된 수
Normalized 된 방식
M = 1.xxx...x₂ (leading 1을 포함한다.)
Denormalized 된 방식
M = 0.xxx...x₂ (leading 1을 포함하지 않는다.)
Case 1 : exp = 000...0, frac = 000...0 (exp, frac 모두 0인 경우 = Zero)
Case 2 : exp = 000...0, frac ≠ 000...0 (exp는 0, frac은 0이 아닌 경우)
Case2는 0.0에 가까운 매우 작은 수이다.
따라서 0.0에 가까운 수를 표현할 때, 비정규환 된 (M=0.xxx) 수를 허용한다.
IEEE 754 표준은 일부 특수 case 들의 표현을 지정하고 있다.
• Google BFloat16
정밀도를 조금 덜 가져가고 bit 수를 줄이기 위해서 구글 내부적으로 사용한다.
float32와 비교하면 16bit가 줄어든 것을 확인해볼 수 있다.
• 부동소수점 곱셈
부동소수점 곱셈은 다음과 순서로 진행된다.
1. 두 숫자의 Exponent를 더한다. (E = E1 + E2)
2. 두 숫자의 mantissa를 곱한다. (M = M1 * M2)
3. 결과를 정규화하고 오버프로우/언더플로우를 확인하다.
- 만약 (M ≥ 2)이면, M을 오른쪽으로 시프트하고 E를 증가시킨다.
- 만약 (M < 1)이면, M을 왼쪽으로 k만큼 시프트하고 E를 k만큼 감소시킨다.
4. 필요시 matissa를 정규화한다. (Rounding)
5. 각 숫자의 부호를 XOR 연산하여 결정한다.
XOR 게이트 추가 등 덧셈에 비해 더 복잡하기 때문에 보통 FP Multiplication을 기준으로 칩의 성능 평가를 진행한다.
또한 빠르게 만들기 어려운 편이다.
• C에서의 FP
기본적으로 float과 double을 지원한다.
datatype 때문에 계산오차가 발생할 수 있다.
• Byte Ordering
빅 엔디안 규칙과 리틀 엔디안 규칙이 있다.
빅 엔디안 : 큰 단위가 낮은 메모리 주소에 배열된다.
리틀 엔디안 : 작은 단위가 낮은 메모리 주소에 배열된다.
메모리 위치에 따른 연산이 진행되는 경우 Bit 순서를 잘 맞춰야한다.
'CS > 컴퓨터구조' 카테고리의 다른 글
[컴퓨터구조] #6 ISA(2) (0) | 2024.04.23 |
---|---|
[컴퓨터구조] #5 ISA(1) (0) | 2024.04.22 |
[컴퓨터구조] #3 정수표현법 (0) | 2024.04.15 |
[컴퓨터구조] #2 성능 (0) | 2024.04.10 |
[컴퓨터구조] #1 컴퓨터구조 (0) | 2024.04.04 |