배포된 서비스에서 점수를 소수점 입력이 가능하도록 변경해야 하는 이슈가 있었다.
현 서비스에서는 mysql + aws rds를 이용해서 운영을 하고, 로컬 테스트를 위해 h2 db에서 테스팅 하는 과정에서 문제가 발생했다.
분명 입력값으로 2.333을 넣었는데, 이런 식으로 소수부분이 깨지는 현상이 발생했다.
Mysql decimal vs float(double)
결론적으로, float와 double 타입의 경우에는 부동 소수점 방식의 데이터 타입이다. 부동소수점(floating point) 방식은,
이진수에서 0과 1을 사용하여 소수를 근사해서 표현하는 방식을 말한다.
사실 부동이라는 단어에서 움직이지 않는다는 뜻이라고 유추했는데, 실제 뜻은 떠다니며 움직인다는 의미라고 한다.
(뜰 부 + 움직일 동)
그러나 decimal은 고정 소수점 타입으로, 소수값을 있는 그대로 표현하는 방식이다. 따라서 위 문제를 해결하기 위해서는 Decimal 타입으로 테이블을 선언하면 해결할 수 있다.
대체 무슨 차이가 있을까? 원리는 생각보다 간단하다.
고정 소수점 방식(Decimal)
고정 소수점 방식이란, 정수를 표현하는 비트 수와 소수를 표현하는 비트 수를 미리 정해 놓고,
해당 비트만 사용해서 수를 표현하는 방식이다.
고정 소수점 방식의 경우, 정수부와 소수부로 나누어 각각 저장하는 방식이다.
빈칸은 0으로 채워진다.
이러한 방법으로 소수 부분을 그대로 저장할 수 있게 된다.
부동 소수점 방식(Float, Double)
부동 소수점 방식의 경우 소수를 이진수로 변환하여 그대로 저장하는 것이 아니라,
정규화(Normalization) 과정을 한 단계 거치게 된다.
예를 들어 이진수로 표현된 10.1011이라는 수가 있다고 하자.
우선 소수에서 맨 앞자리를 제외한 나머지 부분을 모두 소수점 아래로 이동시킨다.(1.01011)
이때, 소수점을 이동시킨 간격(n)만큼 2^n, 2의 거듭제곱 형태로 표현하는 것이다.
이 n을 지수부에 기록하고, 나머지 소수점 이후 숫자 전체를 가수부에 기록하는 방식이다.
IEEE 754 표현 방식에 따르면, 지수부에 bias라는 값을 도입해 해당 값을 n에 더해 저장한다고 한다.
현재 공식적으로 지정된 bias는 127이다.
이런 방식으로 인해, 부동 소수점 방식에서는 소수의 정확한 값을 나타낼 수 없게 된다.
그럼 부동 소수점 방식은 왜 사용하는가?
고정 소수점 방식의 경우 정확성을 보장하지만, 정수부는 15bit, 소수부는 16bit으로 고정적이기 때문에 큰 숫자나 소수 수열 길이가 긴 경우에는 표현하기 어렵다는 단점이 있다.
예를 들어 소수 수열이 한자리인 경우에도, 소수부의 크기는 16bit으로 고정적이므로 해당 공간은 낭비되게 된다.
하지만 부동 소수점 방식의 경우에는 해당 비트 수 대비 표현 가능한 수의 범위가 훨씬 크다.
즉 메모리상의 효율 이점이 생기므로, 현재 대부분의 컴퓨터에서는 부동소수점을 이용해 실수를 표현하고 있다고 한다.
출처
'CS > Database' 카테고리의 다른 글
[DB] 트랜잭션의 격리성과 동시성에 대해(feat. 트랜잭션의 격리 수준) (5) | 2024.07.23 |
---|---|
Replication - 복제 지연 문제에 대해(일관성과 성능 이야기) (0) | 2024.06.17 |
Replication - 리더 기반 복제에 대해 (0) | 2024.06.10 |