【问题标题】:Generating An Amortization Schedule [closed]生成摊销时间表[关闭]
【发布时间】:2008-12-04 22:10:44
【问题描述】:

我的任务是创建一个可以生成摊销计划的程序。到目前为止,我只做了一点研究,但我需要计算付款、每次付款的利息和每次付款的本金。任何人都可以指出我正确的方向来解决这个问题吗?虽然我将在 RPG 中编写这个,但我相信其他人将来可以使用这个算法。

(更新)好的,那么我如何根据一年 365 天计算?

【问题讨论】:

  • 如果应用很重要,我认为你应该问会计师这个问题,并使用会计师会使用的相同公式。即使是“正确”的答案(对于不重要的应用程序来说很好),也可能会产生不符合您所在司法管辖区的会计惯例/法规的结果。
  • 是的,但他们使用供应商程序来计算付款。我需要在我的代码中复制它。当然,我不能只看他们如何计算付款......

标签: algorithm language-agnostic amortization


【解决方案1】:

当我最近买第一套房子时,我写了一个 JavaScript 应用程序供我个人使用。

这是我的代码修改后的 sn-p 以确定每月付款:

var balance = 200000; // for example
var periods = 360; // 30 years
var monthlyRate = (0.065)/12;  // 0.065= APR of 6.5% as decimal
var monthyPayment = (monthlyRate /(1-(Math.pow((1+monthlyRate),-(periods)))))*balance;

for (var i=0; i<360; i++) {
  var interestForMonth = balance * monthlyRate;
  var principalForMonth = monthlyPayment - interestForMonth;
  balance -= monthlyPayment; // probably should be -= principalForMonth see comments below
  // output as necessary.
}

之后很容易制作摊销表。 (正如其他人所提到的,请注意舍入错误,我在实现中没有充分处理这个问题。)

【讨论】:

    【解决方案2】:

    有很多网站提供这些公式。一个如下: http://www.math4finance.com/financial-formulas.php

    不需要花哨的算法,因为公式通常很简单。

    【讨论】:

    • 我不一定需要代码。我只是比维基百科给出的更好的方向。我需要能够为所有付款创建数据库记录集。
    【解决方案3】:

    C# 中的摊销时间表公式

                numerator = i * principle * (Math.Pow(1 + i, n));
                denominator = (Math.Pow(1 + i, n) - 1);
    
                /* Calculation of Amortization Payment Amount  */
                payment = numerator / denominator;
    

    【讨论】:

      【解决方案4】:

      布赖恩是对的。公式很简单。

      如果您希望您的解决方案是一个好的解决方案,您需要注意舍入误差。如果您只是让舍入误差累积并传播,您可以在计划结束时减少几美分。通过仔细编程,您将最大限度地减少错误。

      另外,如果您的计算机上有 MS Excel,您可以从 MS Office 在线下载摊销模板。

      【讨论】:

        【解决方案5】:

        这是我最终创建的。我已经发布了整个测试程序。它是用 RPG 编写的,但对于任何其他语言都应该很容易理解。

         H ActGrp(*caller) BndDir('MODULES') DftActGrp(*no)
           //*********************************************************************
           // Program . . . . . AMORT
           //*********************************************************************
           // Printer/Display Files
         FAMORTDF   CF   E             WORKSTN sfile(SFL01:rrn01)
           //*********************************************************************
           // Named Constants
          /copy modules/qcopysrc,statuscopy
        
           // Named Indicators
         D indicatorPtr    S               *   Inz(%Addr(*IN))
         D                 DS                  Based(IndicatorPtr)
          /copy modules/qcopysrc,scrncopy
        
           // Subfile  Fields
         D rrn01           S              4P 0 inz(0)
        
           //*********************************************************************
           // Misc Fields
         D* Monthly Payment
         D m               S             12P 2        
         D* Principal
         D p               S             12P 2                                      
         D* Interest
         D i               S              5P 3                                      
         D* Length (in Years)
         D l               S              3P 0                                      
         D* Monthly Interest
         D j               S             10P10                                      
         D* # of Months
         D n               S              5P 0                                      
         D* Current Monthly Int.
         D h               S             12P 2                                      
         D* Current Principal
         D c               S             12P 2                                      
         D* New Balance
         D q               S             12P 2                                      
        
           //*********************************************************************
           // External Program Procedures
        
           // Internal Subprocedures
         D Init            PR
         D Main            PR
         D SubfileFilled   PR              N
         D ClearScreen     PR
         D IsValidData     PR              N
         D LoanPayment     PR            12P 2
         D  principal                    12P 2
         D  interest                      5P 3
         D  loanPeriod                    3P 0
         D  paymentsYear                  3P 0
        
           // External Subprocedures
           ///copy modules/qsrvsrc,p.string
        
           //*********************************************************************
           // Entry Parms
         D AMORT           PR                  extpgm('AMORT')
         D AMORT           PI
           //*********************************************************************
          /free
           Init();
           Main();
        
           *inlr = *on;
          /end-free
        
         P*--------------------------------------------------
         P* Procedure name: Init
         P* Purpose:
         P* Returns:
         P*--------------------------------------------------
         P Init            B
         D Init            PI
        
          /free
        
           pgm = 'AMORT';
           sflDsp = *off;
        
           return;
        
          /end-free
         P Init            E
        
        
         P*--------------------------------------------------
         P* Procedure name: Main
         P* Purpose:
         P* Returns:
         P*--------------------------------------------------
         P Main            B
         D Main            PI
        
          /free
        
           dow (not F3) and (not F12);
        
             write OVR01;
             exfmt CTL01;
             ClearScreen();
        
             if (IsValidData()) and (not F3) and (not F12);
        
               // Fill the header information
               dPayment = LoanPayment(dLoanAmt:dIntRate:dLoanPrd:dPayYear);
               dNumPaymnt = dLoanPrd * dPayYear;
               m = dPayment + dExtraPay;
               p = dLoanAmt;
               q = p;
        
               // Fill the table
               if (SubfileFilled());
                 sflDsp = *on;
               endif;
             endif;
        
           enddo;
        
           return;
        
          /end-free
         P Main            E
        
        
         P*--------------------------------------------------
         P* Procedure name: SubfileFilled
         P* Purpose: Fill the subfile
         P* Returns:
         P*--------------------------------------------------
         P SubfileFilled   B
         D SubfileFilled   PI              N
        
         D isFilled        S               N
         D x               S              4P 0
         D intCume         S             12P 2
         D extraPayCume    S             12P 2
         D payDate         S               D
         D payment         S             12P 2
         D extraPayment    S             12P 2
        
          /free
        
           isFilled = *on;
        
           sflClear = *on;
           write CTL01;
           sflClear = *off;
           rrn01 = 0;
           x = 0;
        
           // Setup the work fields
           payment = dPayment;
           extraPayment = dExtraPay;
           payDate = dStartDate;
        
           // Create records until there is a zero balance
           dow (q > 0);
        
             x += 1;
             eval(h) h = p * j; // Monthly Interest
        
             // Adjust for final payment
             if (p < m);
               m = p + h;
               payment = p;
               extraPayment = h;
             endif;
        
             // Calulate Principal
             c = m - h;
             // Calulate the new balance
             q = p - c;
        
             // Accumulate the interest and extra payments
             intCume += h;
             extraPayCume += extraPayment;
        
             // Determine the next pay date
             select;
               when dTerms = '1'; //Yearly
                 payDate += %years(1);
               when dTerms = '2'; //Semi-Annual
                 payDate += %months(6);
               when dTerms = '3'; //Quarterly
                 payDate += %months(3);
               when dTerms = '4'; //Monthly
                 payDate += %months(1);
               when dTerms = '5'; //Bi-Weekly
                 payDate += %days(14);
             endsl;
        
             // Fill the subfile
             sPayNum = x;
             sPayDate = payDate;
             sBegBal = p;
             sSchedPay = payment;
             sExtraPay = extraPayment;
             sTotPay = m;
             sInterest = h;
             sPrincipal = c;
             sEndBal = q;
             sCumeInt = intCume;
        
             // Move the End balance to the beginning balance
             p = q;
        
             rrn01 += 1;
             write SFL01;
        
           enddo;
        
           // Return the calculated information to the header
           dActPaymnt = x;
           dTotInt = intCume;
           dTotEPay = extraPayCume;
        
           if (rrn01 < 1);
             isFilled = *off;
           endif;
        
           return isFilled;
        
          /end-free
         P SubfileFilled   E
        
        
         P*--------------------------------------------------
         P* Procedure name: ClearScreen
         P* Purpose:
         P* Returns:
         P*--------------------------------------------------
         P ClearScreen     B
         D ClearScreen     PI
        
          /free
        
           c = 0;
           h = 0;
           i = 0;
           j = 0;
           l = 0;
           m = 0;
           n = 0;
           p = 0;
           q = 0;
           dPayment = 0;
           dNumPaymnt = 0;
           dActPaymnt = 0;
           dTotEPay = 0;
           dTotInt = 0;
        
           return;
        
          /end-free
         P ClearScreen     E
        
        
         P*--------------------------------------------------
         P* Procedure name: IsValidData
         P* Purpose: Validate the data on the screen
         P* Returns: True or False
         P*--------------------------------------------------
         P IsValidData     B
         D IsValidData     PI              N
        
         D isValid         S               N
        
          /free
        
           if (dLoanAmt <> 0) and (dIntRate <> 0) and (dLoanPrd <> 0) and
              (dPayYear <> 0) and (dStartDate <> %date('0001-01-01'));
             isValid = *on;
           else;
             isValid = *off;
           endif;
        
           return isValid;
        
          /end-free
         P IsValidData     E
        
        
         P*--------------------------------------------------
         P* Procedure name: LoanPayment
         P* Purpose: Calculates the payment
         P* Returns:
         P*--------------------------------------------------
         P LoanPayment     B
         D LoanPayment     PI            12P 2
         D  principal                    12P 2
         D  interest                      5P 3
         D  loanPeriod                    3P 0
         D  paymentsYear                  3P 0
        
         D retMonthlyPayment...
         D                 S             12P 2
        
          /free
        
           eval(h) n = loanPeriod * paymentsYear;
           eval(h) j = interest / (paymentsYear * 100);
        
           eval(h) m = principal * (j / (1 - (1 + j) ** -n));
        
           return m;
        
          /end-free
         P LoanPayment     E
        

        此代码已针对我们的贷款计算器进行了测试。如果 test vs. Excel,200,000 美元的贷款减少了大约 32 美分。我确信这对四舍五入问题有帮助。

        【讨论】:

          【解决方案6】:
          var annuity =  P * (i + i / (Math.pow(1+i,n) -1));
          
          //P: principal, I: periodic interest rate, N: number of periods
          

          【讨论】:

            猜你喜欢
            • 2021-04-03
            • 1970-01-01
            • 2010-09-17
            • 1970-01-01
            • 2014-02-20
            • 2011-06-18
            • 1970-01-01
            • 2023-02-01
            相关资源
            最近更新 更多