계산 정확도
연 수익률을 12로 나누면 안 되는 이유
r/12로 나눠 12개월 복리를 돌리면 입력한 연 수익률보다 커진다. 기하평균으로 환산해야 정확히 맞는다.
연 7%를 월로 바꾸면 몇 퍼센트인가
매달 일정액을 적립했을 때의 미래가치를 계산하려면 월 단위 수익률이 필요합니다. 연 수익률 7%가 주어졌을 때 월 수익률을 어떻게 구할까요.
가장 먼저 떠오르는 건 7 / 12 = 0.5833%입니다. 간단하고 직관적입니다. 그리고 틀립니다.
12번 곱하면 7%가 넘는다
월 0.5833%로 12개월을 굴려 봅니다.
(1 + 0.005833) ** 12 - 1 = 0.0723 // 7.23%입력한 7%가 아니라 7.23%가 나옵니다. 복리가 복리를 낳기 때문입니다. 사용자는 7%를 넣었는데 계산기는 조용히 7.23%로 굴린 셈입니다.
차이가 작아 보이지만 기간이 길어지면 벌어집니다. 그리고 무엇보다, 사용자가 입력한 값과 계산에 쓰인 값이 다른 것 자체가 문제입니다. 금융 관련 숫자를 다루는 도구에서는 특히 그렇습니다.
기하평균으로 환산한다
올바른 환산은 12번 곱했을 때 정확히 연 수익률이 되는 값을 찾는 것입니다. 즉 12제곱근입니다.
monthlyRate = (1 + annualRate / 100) ** (1 / 12) - 1연 7%를 넣으면 월 0.5654%가 나오고, 이걸 12번 굴리면 정확히 7%가 됩니다. 산술평균이 아니라 기하평균을 쓰는 것이고, 복리 계산에서는 이쪽이 맞습니다.
0으로 나누는 지점
적립식 미래가치는 등비급수 공식으로 구합니다. 그런데 이 공식에는 함정이 있습니다.수익률이 0%일 때 분모가 0이 됩니다.
사용자가 수익률 슬라이더를 0으로 놓는 건 아주 자연스러운 동작입니다. "그냥 모으기만 하면 얼마지?"를 보고 싶을 때 누구나 그렇게 합니다. 그 자리에서 NaN이나 Infinity가 뜨면 안 됩니다.
그래서 월 수익률의 절댓값이 1e-12보다 작으면 등비급수 대신 단순 곱셈(월 납입액 × 개월 수)으로 분기합니다. 수익률이 0이면 미래가치는 원금과 같으니까요.
임계값을 정확히 0이 아니라 1e-12로 잡은 이유도 있습니다. 부동소수점 연산을 거치면 0이 정확히 0으로 남지 않을 수 있기 때문입니다. 0.0000000001% 같은 값이 들어와도 분모가 사실상 0이라 같은 문제가 납니다.
이런 건 손으로 검산이 안 된다
복리 계산은 암산으로 확인할 수 없습니다. 그래서 이 도구는구현 전에 정답표 30개를 실제로 계산해 스펙 문서에 적었습니다.수익률 0%, 음수, 극단값 같은 경계 케이스를 전부 포함해서요.
구현이 끝난 뒤 테스트가 그 30개를 그대로 통과했습니다. 순서를 이렇게 잡으면 코드와 문서가 어긋날 여지가 없습니다. 구현하고 나서 "나온 값"을 기대값으로 적으면, 틀린 값을 기대값으로 굳히게 됩니다.