Ejemplo n.º 1
0
        /// <summary>
        /// Calculates the minimum payment for a loan.
        /// </summary>
        /// <param name="rate">The periodic interest rate (applied every period). This must be greater than or equal to zero.</param>
        /// <param name="numberOfPeriods">The number of periods remaining on the loan.</param>
        /// <param name="currentBalance">The current balance of the loan. This must be greater than or equal to zero and not contain fractional pennies.</param>
        /// <param name="futureBalance">The future balance of the loan. This must be greater than or equal to zero and not contain fractional pennies.</param>
        /// <param name="payAtBeginningOfPeriod">Set to <c>true</c> to indicate payments are made at the beginning of the period; by default, payments are made at the end of the period.</param>
        /// <returns>The minimum payment made each period.</returns>
        /// <exception cref="InvalidOperationException">The payment could not be calculated.</exception>
        public static decimal Payment(decimal rate, uint numberOfPeriods, decimal currentBalance, decimal futureBalance = decimal.Zero, bool payAtBeginningOfPeriod = false)
        {
            Contract.Requires <ArgumentOutOfRangeException>(rate >= 0, "Rate may not be less than zero.");
            VerifyMoneyArgument(currentBalance, "currentBalance");
            VerifyMoneyArgument(futureBalance, "futureBalance");

            var result = -Exact.Payment(rate, numberOfPeriods, currentBalance, futureBalance, payAtBeginningOfPeriod);

            if (result < decimal.Zero)
            {
                var e = new InvalidOperationException("The payment could not be calculated.");
                e.Data["rate"]                   = rate;
                e.Data["numberOfPeriods"]        = numberOfPeriods;
                e.Data["currentBalance"]         = currentBalance;
                e.Data["futureBalance"]          = futureBalance;
                e.Data["payAtBeginningOfPeriod"] = payAtBeginningOfPeriod;
                e.Data["result"]                 = result;
                throw e;
            }

            try
            {
                return(checked (Math.Ceiling(result * 100) / 100));
            }
            catch (OverflowException ex)
            {
                var e = new InvalidOperationException("The payment could not be calculated.", ex);
                e.Data["rate"]                   = rate;
                e.Data["numberOfPeriods"]        = numberOfPeriods;
                e.Data["currentBalance"]         = currentBalance;
                e.Data["futureBalance"]          = futureBalance;
                e.Data["payAtBeginningOfPeriod"] = payAtBeginningOfPeriod;
                e.Data["result"]                 = result;
                throw e;
            }
        }