[TopCoder] AutoLoan (자동차 할부)

2023. 3. 1. 17:24Algorithm

자동차 대리점들은 사람들이 "꿈의 차"를 더 쉽게 구입할 수 있도록 유혹적인 대출 제안을 자주 광고한다. 일반적인 판매 전략은 다양한 자동차를 보여주고 나서 실제로 자동차에 얼마를 지불하고 있는지, 이자를 얼마나 지불해야 하는지, 지불해야 하는 기간은 말할 것도 없이 월 지불액이 얼마인지에 대해 이야기하는 것입니다.

일반적인 자동차 대출은 고정 금리를 사용하여 계산되며, 잔액을 완전히 상환하기 위해 정해진 기간 동안 동일한 월 납입을 하도록 설정됩니다. 당신의 대출 잔액은 자동차의 스티커 가격으로 시작한다. 매월 이자는 잔액에 가산되며, 지불 금액은 잔액에서 차감됩니다. (이자가 가산된 후에 지급액이 차감됩니다.) 월 이자율은 연 이자율의 12분의 1이다. 따라서 연간 백분율이 12%인 경우 남은 잔액의 1%가 매달 이자로 청구됩니다.

귀하는 지역 대리점인 TopAuto에서 일부 차량을 점검해 왔습니다. 흥분한 세일즈맨이 방금 여러분에게 다가와서, 여러분이 보고 있는 자동차를 어떻게 loanTerm 동안만 monthlyPayment을 지불할 수 있는지에 대해 소리쳤습니다! 당신은 대출의 초기 잔액이 price이라고 가정하고 대출의 연간 비율을 나타내는 double를 반환해야 한다.

Definition

Class: AutoLoan
Method:
 
interestRate
Parameters:
 
double, double, int
Returns:
 
double
Method signature:
 
double interestRate(double price, double monthlyPayment, int loanTerm)

 

(be sure your method is public)

Notes

- Because of the way interest is compounded monthly, the actual interest accrued over the course of a year is not necessarily the same as (balance * yearly interest rate). In fact, it's usually more.
- In a real situation, information like this would typically need to be disclosed, but since you aren't at a point of signing any paperwork, the salesman has no legal obligation to tell you anything.
- The return value must be within 1e-9 absolute or relative error of the actual result.
 

Examples

0)
6800
100
68
Returns: 1.3322616182218813E-13
Noting that 68 payments of 100 equals the total price of 6800, so there is no interest.
1)
2000
510
4
Returns: 9.56205462458368
Here, we do pay a little interest. At 9.562% annual interest, that means each month we pay 0.7968% of the balance in interest. Our payment schedule looks like this:
Month | + Interest | - Payment | = Balance
------------------------------------------
      |            |           |  2000.00
   1  |     15.94  |   510.00  |  1505.94
   2  |     12.00  |   510.00  |  1007.94
   3  |      8.03  |   510.00  |   505.97
   4  |      4.03  |   510.00  |     0.00
2)
15000
364
48
Returns: 7.687856394581649
This is similar to what purchasing a new car with no money down might look like, if you make payments for 4 years.

The return value must be within 1e-9 absolute or relative error of the actual result.

→ 이분 탐색으로 푸는 문제이다. 


#include <algorithm>
#include <cmath>
using namespace std;

class AutoLoan{
    public:
    double interestRate(double price, double monthlyPayment, int loanTerm){
        double monthIntr;
        double loan;
        double upper = 100;
        double lower = 0;
        double interest = (upper+lower)/2;

최종 반환하고자 하는 이자인 interest는 0 ~ 100 사이의 범위이므로 이 절반의 값으로 초기 설정한다. 

        while((1e-9 < upper-lower) && 1e-9<(upper-lower)/upper){

그리고 절대 오차와 상대오차가 1e-9 이하가 되면 while문을 탈출하는 것으로 조건을 설정한다. 

 

            monthIntr = 0.01*interest/12;
            loan = price;
            //빚을 차 금액으로 초기화
            for(int i=0; i<loanTerm; i++){
                loan += monthIntr*loan;
                //전체 빚에 월이자 추가
                loan -= monthlyPayment;
                //월납부만큼 차감
            }

월 이자금액을 계산하고, 전체 빚(loan)을 차의 금액으로 설정한다. 

 

그리고 loanTerm만큼 월 이자를 얹고, 월 납부금액만큼 차감하였을 때 결과적으로 남은 빚이 0에 가까워야 

 

우리가 추정한 interest가 옳은 이자율이 된다. 

 

            //laonTerm만큼 돌렸는데
            if(loan>0){
                //남은 빚이 더 남아있으면 추정한 이자가 과도한 것이므로
                upper = interest;
                interest = (interest + lower)/2;
                // 더 줄인다.
            }

빚을 갚는 Simulation을 돌렸으나 빚이 남아 있으면 매달 얹어지는 이자가 너무 과도하므로 이자율을 더 줄여야한다. 

 

상한을 현재의 interest로 바꿔주고, 이자율을 반토막 낸다. 

 

            else if(loan<0){
                //남은 빚이 오히려 마이너스이면 추정된 이자가 작은 것이므로
                lower = interest;
                interest = (upper + interest)/2;
                // 더 늘린다.
            }

반대로 빚이 오히려 마이너스이면 매달 얹혀지는 이자가 작은 것이므로 

 

하한을 현재의 interest로 설정하고 빚을 증액한다. 

 

        }
        return interest;

while 문 탈출 시 interest를 반환한다.