은행 현장의 언어 · 금액을 실수로 다루면 생기는 오차 · 실습
합계가 3원 안 맞는데 어느 줄도 틀리지 않았다
목표
통화마다 다른 최소단위를 표로 만들고, 수수료 원장을 정수 최소단위로 다시 적재하고, 반올림 모드를 정책으로 못박고, 나머지 1까지 맞는 배분과 환산 순서에 따른 차이를 산출물로 남긴다.
왜 중요한가
금액을 실수로 다루면 한 줄에 1씩 어긋나고, 그 정도는 단위 시험이 잡지 못한다. 합계가 안 맞는다는 문의가 들어와도 어느 줄이 틀렸는지 짚을 수 없어서 "다시 돌리면 맞는다" 는 운영 절차가 생긴다.
여기서 정하는 것은 세 가지다. 저장 형식(정수 최소단위), 끊는 자리와 반올림 모드(정책), 나머지 배분 규칙(최대잉여법). 셋 다 기술이 정해 주지 않고 사람이 정해 문서에 적어야 하는 것이다.
채점기는 여러분이 적은 숫자끼리 비교하지 않는다. 1단계에서 만든 원자료에서 기준값을 다시 계산해 대조한다. 그래서 규칙을 그대로 따르는 것이 중요하다.
단계
1. /root/money/gen_money.py 를 만들어 실행해 /root/money/currencies.json, /root/money/fees.csv(600행), /root/money/splits.csv(30건)를 만든다.
2. 가산율 0.125 를 실수 경로와 정수 경로로 각각 계산해 /root/money/float_gap.json 에 어긋난 줄 수와 차이를 적는다.
3. /root/money/money.db 에 fee(정수 최소단위)와 fee_real(REAL) 두 표로 적재하고 /root/money/store.json 에 통화별 두 합계를 적는다.
4. /root/money/money_fmt.py 에 파싱과 표시를 모으고, 안내의 입력 12개를 판정해 /root/money/format_check.json 을 만든다.
5. 같은 곱셈을 ROUND_HALF_UP 과 ROUND_HALF_EVEN 으로 끊어 /root/money/rounding.json 에 갈라진 줄 수와 두 합계를 적는다.
6. splits.csv 의 30건을 최대잉여법으로 배분해 /root/money/alloc.json 에 적는다. 합계는 총액과 정확히 같아야 한다.
7. 안내의 환율표로 통화 5종을 원화로 환산해 /root/money/fx.json 에 줄 단위와 총액 단위 두 값을 적는다.
8. 앞 단계의 결과를 /root/money/report.json 하나로 묶고 fees.csv 의 sha256 을 함께 적는다.
참고
- 1단계 생성 규칙: 통화는 KRW,JPY,USD,KWD,BHD,CLP 를 이 순서로 돌려 쓰고(row_id 를 6으로 나눈 나머지), row_id 는 0 부터 599, 최소단위 금액은
1000 + (row_id * 37) % 9001, amount_text 는 그 금액을 통화의 소수 자리로 표시한 글자다. - 1단계 배분 규칙: case_id 는 0 부터 29, 통화는 KRW,USD,KWD 를 돌려 쓰고, total_minor 는
100000 + case_id * 7777, 가중치는1 + (case_id*3) % 9,1 + (case_id*5) % 7,1 + (case_id*7) % 5이다. - 2단계 두 경로: 실수 쪽은
int(round(round(float(amount_text) * 0.125, 소수자리) * 10 ** 소수자리)), 정수 쪽은Decimal(amount_text) * Decimal("0.125")를 소수 자리에서 ROUND_HALF_UP 으로 quantize 한 뒤 최소단위로 바꾼 값이다. - 4단계 입력 12개:
KRW 1234,JPY 0,USD 0.05,KWD 0.001,BHD 12.345,CLP 99,USD 1234567.89,USD 1.234,KRW 12.5,XAU 1.0,ZZZ 5,USD 1,234.56. 거절 사유는too_many_minor_digits,unknown_minor_units,unknown_currency,not_a_number네 가지만 쓴다. - 7단계 환율표(원화 기준, 소수 넷째 자리): JPY 9.0421 · USD 1381.5027 · KWD 4512.3007 · BHD 3665.1420 · CLP 1.4508. 이 숫자는 이 실습의 가정입니다 — 실제 고시환율이 아니라 소수 넷째 자리라는 계약을 보이려고 지어낸 값입니다. 통화별 소수 자리(최소단위)만 ISO 4217 의 실제 값입니다.
- 흔한 실수: 파이썬 내장
round()가 은행가 반올림이라는 것을 잊기, 엔화에 소수점 붙이기, 배분에서 나머지 버리기, 환산 순서를 섞기. - 확인:
python3 -c "import json;print(json.load(open('/root/money/float_gap.json'))['mismatch_rows'])"
단계 8개
- 통화표와 수수료 원장 만들기
- 실수로 계산한 가산금이 몇 줄이나 어긋나는가
- 정수 최소단위로 다시 적재하기
- 파싱과 표시를 한 문으로 모으기
- 반올림 모드를 정책으로 못박기
- 나머지 1까지 맞는 배분
- 환산 순서가 결과를 바꾼다
- 여섯 단계를 보고서 하나로 묶기