컴퓨터는 실수를 정확하게 저장하기 어렵습니다. 왜냐하면 10진수의 소수를 2진수로 바꿀 때, 정확하게 표현되지 않는 수가 많기 때문입니다. 예를 들어 0.1은 2진수로 정확하게 표현되지 않습니다. 그래서 컴퓨터는 실수를 저장할 때 부동소수점(Floating Point) 방식으로 근사해서 저장합니다.
부동소수점의 근사 표현 방식 때문에 다음과 같은 문제가 발생할 수 있습니다:
1991년 걸프전, 미군의 패트리어트 미사일 시스템이 이라크 스커드 미사일을 격추하지 못한 사건이 있었습니다. 그 이유는 바로 부동소수점 오차 때문이었습니다.
작은 오차도 누적되면 치명적인 결과를 초래할 수 있다
부동소수점 오차를 줄이기 위한 대표적인 방법은 다음과 같습니다:
금액, 거리 등 단위를 고정할 수 있는 경우에는 정수형으로 처리하는 것이 좋습니다.
// Flutter 예제 - 금액을 cents 단위로 처리
int priceA = 1500; // $15.00
int priceB = 299; // $2.99
int total = priceA + priceB;
print('Total in cents: $total'); // 1799
print('Total in dollars: \$${(total / 100).toStringAsFixed(2)}'); // $17.99
비교 시 정확한 일치 대신 허용 오차(Epsilon) 범위를 둡니다.
// Flutter 예제 - 부동소수점 비교
bool isAlmostEqual(double a, double b, [double epsilon = 0.00001]) {
return (a - b).abs() < epsilon;
}
void main() {
double x = 0.1 + 0.2;
double y = 0.3;
print('x: $x'); // 0.30000000000000004
print('isAlmostEqual: ${isAlmostEqual(x, y)}'); // true
}
Dart에서는 decimal 패키지처럼 정확한 수치 연산이 가능한 라이브러리를 사용할 수 있습니다.
import 'package:decimal/decimal.dart';
void main() {
Decimal a = Decimal.parse('0.1');
Decimal b = Decimal.parse('0.2');
Decimal c = a + b;
print('Result: $c'); // 0.3
}
부동소수점은 컴퓨터가 실수를 표현하는 방식의 본질적인 한계 때문에 완벽하지 않습니다. 특히 정밀 계산이 필요한 분야(금융, 과학, 방위산업 등)에서는 반드시 오차를 고려한 설계가 필요합니다.
Flutter나 Dart에서 개발할 때도 비교 연산, 금액 처리 등을 할 때 정수 처리나 오차 허용 범위 비교, 정밀 연산 라이브러리 사용을 적극 활용하면 문제를 예방할 수 있습니다.