BigDecimal 라이브러리의 주요 문제점과 개선 방안
BigDecimal 라이브러리는 Ruby에 추가된 지 오래되었으나, 여러 고질적인 문제를 안고 있습니다. 주요 문제점은 다음과 같습니다.
1. 전역 동작 모드 관리
-
문제점: BigDecimal의 예외 모드(무한대/NaN 발생 시 예외 처리)와 반올림 모드(지정된 자릿수 초과 시 처리 방식)가 프로세스 단위의 전역 변수로 관리되어 스레드 및 파이버 안전성을 보장하지 못했습니다. 이로 인해 여러 스레드에서 다른 모드를 동시에 사용할 경우 예측 불가능한 결과가 발생했습니다.
-
개선: 발표자는 이 문제를 스레드 로컬 스토리지(Thread Local Storage) 방식으로 전환하여 각 스레드가 독립적인 모드를 가질 수 있도록 수정했습니다. 또한,
BigDecimal.save_exception_mode와BigDecimal.save_rounding_mode와 같은 블록 기반 메서드를 추가하여 특정 블록 내에서만 임시적으로 모드를 변경하고 블록 종료 시 원래 모드로 복원하는 기능을 도입했습니다.
2. 유효 숫자(Significant Digits) 처리
-
문제점: BigDecimal은 현재 숫자의 유효 숫자를 직접 관리하지 못하며,
prec메서드는 내부 메모리 할당 정보만을 반환합니다. 이는 사용자가 원하는 ‘의미 있는 자릿수’ 정보와는 다릅니다. 또한, BigDecimal과 Float를 혼용할 경우, BigDecimal의 정밀도가 Float의 최대 정밀도(일반적으로 15자리)로 강제 변환되어 데이터 손실 및 오차가 발생할 수 있습니다. -
개선 방향: 숫자가 스스로 유효 숫자를 인지하고 연산 시 자동으로 결과의 유효 숫자를 결정하는 방식이 필요합니다. 오차(error margin, σ)를 기록하는 방식도 대안으로 제시되었습니다.
3. 인스턴스 생성의 제약
-
문제점: BigDecimal은 문자열로부터는 인스턴스 생성이 가능하나,
Integer,Rational,Float등 다른 수치 클래스로부터는 직접 생성이 불가능하며 예외를 발생시킵니다. 심지어BigDecimal(BigDecimal.new('1'))과 같이 자기 자신의 인스턴스를 전달해도 예외가 발생하는 명백한 버그가 존재합니다. -
개선 방향:
Integer로부터의 생성은 버그로 간주하여 수정 예정입니다.Rational과Float로부터의 생성은 진수 변환 및 정밀도 지정의 복잡성으로 인해 신중한 설계가 필요합니다.
4. 계산 속도
-
문제점: 덧셈과 곱셈이 초등학교 수준의 필산 방식으로 구현되어 있어 대규모 계산에서 속도가 느립니다.
-
개선 방향:
Bignum에 이미 적용된 카라츠바(Karatsuba) 곱셈법과 같은 고속 알고리즘을 도입하고, 나눗셈에는 뉴턴법(Newton’s method)을 활용하여 역수를 구하는 방식을 적용할 계획입니다.
Ruby 수치 시스템의 미래: 계산 가능 수(Computable Numbers)
현재 Ruby의 수치 시스템은 정수(Integer), 유리수(Rational), 실수(Float, BigDecimal), 복소수(Complex)를 지원하지만, 무리수를 정확하게 표현하는 클래스는 부재합니다. 발표자는 무리수를 생성하는 알고리즘 자체를 객체화하여 ‘계산 가능 수’로 표현하고, 이를 통해 모든 수직선상의 점을 정확히 다룰 수 있는 새로운 수치 시스템을 제안합니다. 이는 불필요한 계산을 줄이고 e^(-iπ) = -1과 같은 복소수 계산 결과를 -1.0이 아닌 -1로 정확히 반환하는 등 더 정교한 수치 연산을 가능하게 할 것입니다.