728x90
컴퓨터에서의 실수 표현 방식
컴퓨터에서 실수를 표현하는 방식에는 두 가지가 있다.
- 고정 소수점(Fixed Point) 방식
- 부동 소수점(Floating Point) 방식
고정 소수점(Fixed Point) 이란?
고정 소수점(fixed point)은 정수를 표현하는 비트와 소수를 표현하는 비트 수를 미리 고정하여, 해당 비트만을 활용하여 실수를 표현하는 방식이다.
개념 및 원리
- 처음 1비트는 부호(Sign)를 나타낸다. 양수는
0
, 음수는1
. - 다음 15비트는 정수부(Integer Part)를 나타낸다.
- 다음 16비트는 소수부(Fractional Part)를 나타낸다.
- 정수부와 소수부의 경계를 소수점의 위치로 고정하여, 2진수로 변환된 수를 그대로 저장한다.
- 마지막으로 남는 자리는 모두
0
으로 채운다.
이러한 방식으로 실수를 표현하면 특정한 범위 내에서 정밀하게 실수를 표현할 수 있으며, 하드웨어에서 효율적인 연산이 가능하다.
예제
7.625 (10) = 2² × 1 + 2¹ ×1 + 2⁰ ×1 + 2⁻¹ ×1 + 2⁻² ×0 + 2⁻³ ×1
= 111.101(2)
장점과 단점
장점 | 단점 |
---|---|
연산이 빠르고 효율적 | 표현 가능한 범위가 제한됨 |
특정한 범위에서 높은 정밀도 유지 | 오버플로우 및 언더플로우 위험 |
일정한 비트 수로 메모리 관리 용이 | 작은 값 표현 시 부정확한 결과 발생 가능 |
부동 소수점(Floating Point) 이란?
부동 소수점(floating point) 방식은 실수를 보다 유연하고 넓은 범위에서 표현할 수 있도록 한 방식이다. 소수점의 위치가 고정되지 않고, 지수(exponent)와 가수(mantissa)의 조합을 이용해 실수를 표현한다.
개념 및 원리
부동 소수점 표현 방식에서는 숫자를 아래와 같은 형태로 저장한다.
숫자 = 부호(Sign) × 가수(Mantissa) × 2^지수(Exponent)
IEEE 754 표준
형식 | 부호(Sign) | 지수부(Exponent) | 가수부(Mantissa) |
---|---|---|---|
단정밀도 (32비트) | 1비트 | 8비트 | 23비트 |
배정밀도 (64비트) | 1비트 | 11비트 | 52비트 |
장점과 단점
장점 | 단점 |
---|---|
넓은 표현 범위 제공 | 특정한 10진수를 정확하게 표현 불가 |
동적 정밀도 지원 | 연산 시 오차 발생 가능 |
다양한 수를 다룰 때 연산의 유연성 제공 | 연산 비용이 높아 성능 저하 가능 |
부동 소수점 오류
1. 근사 오류 (소수점 정밀도 문제)
부동 소수점 연산은 무한소수를 정확하게 표현하지 못하기 때문에 오차가 발생할 수 있다.
public class Main {
public static void main(String[] args) {
double a = 0.1;
double b = 0.2;
double sum = a + b;
System.out.println(sum); // 출력: 0.30000000000000004
}
}
2. 연산 순서에 따른 오차 누적
public class Main {
public static void main(String[] args) {
double x = 1.0;
double y = 1e-16;
System.out.println((x + y) - x); // 1e-16이 아니라 0이 나올 수 있음
}
}
3. 대표적인 예제 (0.1 + 0.2 ≠ 0.3 문제)
0.1(10) → 0.0001100110011001100110011001100...(2)
0.2(10) → 0.0011001100110011001100110011001...(2)
0.3(10) → 0.0100110011001100110011001100110...(2)
부동 소수점 오류 해결 방법
1. 정수 연산을 활용한 해결 방법
public class Main {
public static void main(String[] args) {
int a = 10;
int b = 20;
int sum = a + b;
System.out.println(sum / 10.0); // 0.3 정확하게 출력
}
}
2. 여러 언어에서의 해결책
Python
from decimal import Decimal
a = Decimal('0.1')
b = Decimal('0.2')
print(a + b) # 정확히 0.3 출력
C++ (GMP 라이브러리 활용)
#include <iostream>
#include <gmpxx.h>
int main() {
mpf_class a("0.1"), b("0.2");
mpf_class sum = a + b;
std::cout << sum << std::endl; // 정확히 0.3 출력
return 0;
}
Java (BigDecimal 활용)
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
System.out.println(a.add(b)); // 정확히 0.3 출력
}
}
JavaScript (Big.js 활용)
const Big = require('big.js');
let a = new Big('0.1');
let b = new Big('0.2');
console.log(a.plus(b).toString()); // 정확히 0.3 출력
이러한 방법들을 활용하면 부동 소수점 연산에서 발생하는 오류를 효과적으로 줄일 수 있다.
728x90
'Computer Science' 카테고리의 다른 글
[CS] JPG 와 PNG에 대해서 알아보자. (0) | 2024.06.13 |
---|---|
[CS] 부동 소수점 오류 (0) | 2024.06.01 |