새 분야를 조사할 일이 생겨 단위부터 봤다.
1 BTC
0.01 BTC
0.001 BTC
0.000001 BTC
0.00000001 BTC
최소 단위가 소수점 여덟 자리까지 있었다. DECIMAL 로 치면 소수부가 8 이다.
Table of contents
Open Table of contents
왜 이렇게 작나
우리가 쓰는 돈은 최소 단위가 1 원이고 소수점이 없다. INT 하나로 끝난다. 여덟 자리는 처음에 이해가 안 됐다.
읽어 보니 이 화폐는 총량이 정해져 있었다. 필요하면 더 찍는 방식이 아니라 상한이 있는 방식이다. 여기서 이유가 갈렸다.
총량이 고정이면 나누는 수밖에 없다
총량이 고정인데 쓰는 사람이 늘면 더 찍을 수가 없으므로 한 단위를 잘게 쪼개는 수밖에 없다. 값이 오르면 더 그렇다. 한 단위가 커피 한 잔 값일 때는 그대로 쓸 수 있지만 자동차 한 대 값이 되면 작은 거래를 못 한다.
자릿수를 나중에 늘리면 이미 기록된 값들과 안 맞는다. 그래서 처음에 넉넉히 잡아 둔 것으로 보인다. 나중에 바꿀 수 없는 것을 처음에 정해 둔 셈이다.
검증 — 저장 방식을 따져 봤다
여기서 프로그램 쪽이 걱정됐다. 소수점 여덟 자리를 실수형에 담으면 근사값이라 계산할 때마다 오차가 쌓인다. IEEE 754 는 2진 분수로 값을 만드는데 0.1 이나 0.01 은 2진으로 유한하게 안 떨어진다. 돈은 오차가 나면 안 된다.
최소 단위를 1 로 세는 방법이 떠올랐다.
0.00000001 을 1 로 센다
1 BTC = 100,000,000
정수로 세고 표시할 때만 나누면 오차가 안 생긴다. 대신 수가 커져서 1 단위가 1억이고 1,000 단위면 1,000억이다.
총량이 수천만 단위라면 곱해서 수천조가 된다. 32비트 부호 있는 정수의 최대는 2,147,483,647 로 약 21억이니 턱없이 모자란다. 64비트는 약 922경까지라 여유가 있다. MySQL 이면 INT 가 아니라 BIGINT 다.
실수형으로 담는다면 크기 쪽에도 한계가 하나 더 있다. IEEE 754 배정밀도가 정수를 정확히 표현하는 범위는 2의 53승까지이고 그 수가 약 900조다. 수천조가 그 아래이긴 하지만 여유가 몇 배 남짓이다. 크기보다 앞서 걸리는 것은 소수 표현 쪽이다.
이 계산을 하고 나서 보인 것이 있다. 최소 단위를 얼마로 할지와 총량이 얼마인지가 정해지면 저장할 자료형이 따라 나온다. BIGINT 로 세는 쪽과 DECIMAL(16,8) 로 담는 쪽이 갈리는 지점도 거기다. 거꾸로 자료형을 먼저 정하고 그 범위 안에서 총량과 최소 단위를 정할 수도 있다.
단위 이름
각 자릿수에 이름이 붙어 있었다.
0.01 센티
0.001 밀리
0.000001 마이크로
국제 단위계 접두어를 그대로 빌린 것이었다. milli 와 micro 는 길이나 무게에서 이미 쓰는 것이라 새로 외울 것이 없다. 새 이름을 만들면 그만큼 외워야 하는데 익숙한 규칙을 가져오면 그 비용이 없어진다.
가장 작은 단위만 이름이 다르다. 접두어 규칙으로는 nano 가 될 자리인데 만든 사람 이름에서 딴 별칭이 붙어 있다. 가장 작은 단위라 특별하게 본 것 같은데 규칙에서 벗어나니 이것만 따로 외워야 한다. 일관성과 의미 중 하나를 고른 셈이다.
조사를 하면서 단위를 보는 눈이 좀 달라졌다. 단위는 그냥 정하는 숫자라고 생각했는데 총량과 값의 변화와 저장 방식이 다 얽혀 있었다.
정리
- 최소 단위가 소수점 여덟 자리까지 있다 —
DECIMAL로 치면 소수부가 8 이다 - 총량이 고정이라 더 못 만들고 나누는 수밖에 없다
- 값이 오르면 작은 거래를 하려고 잘게 나눠야 한다
- 자릿수를 나중에 늘리면 이미 기록된 값들과 안 맞는다
- 돈은 오차가 나면 안 되니 정수로 세고 표시할 때만 나눈다
- IEEE 754 는 0.1 이나 0.01 을 2진으로 유한하게 못 담는다
- 그러면 수가 커져서
INT가 아니라BIGINT가 필요하다 - 32비트는 약 21억, 64비트는 약 922경까지다
milli와micro같은 익숙한 접두어를 빌리면 새로 안 외워도 된다- 하나만 예외인데 일관성과 의미 중 하나를 고른 것으로 보인다