Создать цикл для графика амортизации в Swift

Я рассчитываю на простой цикл для расчета графика амортизации в Swift.

Итак, вот моя установка на Playground:

let loanAmount: Double = 250000.00
let intRate: Double = 4.0
let years: Double = 30.0

var r: Double = intRate / 1200
var n: Double = years * 12
var rPower: Double = pow(1 + r, n)

var monthlyPayment: Double = loanAmount * r * rPower / (rPower - 1)
var annualPayment: Double = monthlyPayment * 12

Для реального цикла я не уверен, как исправить код ниже.

for i in 0...360 {

  var interestPayment: Double = loanAmount * r
  var principalPayment: Double = monthlyPayment - interestPayment
  var balance: Double; -= principalPayment
}

Нужно составить месячный график. Заранее спасибо за любой совет.

1 ответ

Решение

Я предполагаю, что вы хотите объявить balance переменная вне цикла, и уменьшить ее внутри цикла:

// stylistically, in Swift it's usual to leave
// off the types like Double unless you have a
// reason to be explicit
let loanAmount = 250_000.00
let intRate = 4.0
let years = 30.0

// since these are one-off calculations, you
// should use let for them, too.  let doesn't
// just have to be for constant numbers, it just
// means the number can't change once calculated.
let r = intRate / 1200
let n = years * 12
let rPower = pow(1 + r, n)

// like above, these aren't changing.  always prefer let
// over var unless you really need to vary the value
let monthlyPayment = loanAmount * r * rPower / (rPower - 1)
let annualPayment = monthlyPayment * 12

// this is the only variable you intend to "vary"
// so does need to be a var
var balance = loanAmount

// start counting from 1 not 0 if you want to use an open
// (i.e. including 360) range, or you'll perform 361 calculations:
for i in 1...360 {
    // you probably want to calculate interest 
    // from balance rather than initial principal
    let interestPayment = balance * r
    let principalPayment = monthlyPayment - interestPayment

    balance -= principalPayment
    println(balance)
}

Это должно распечатать правильные сальдо до нуля для окончательного сальдо (ну на самом деле 9.73727765085641e-09 - но это совсем другой вопрос).

Если вы хотите создать ежемесячный баланс, скажем, в массиве, вы можете добавить дополнительную переменную массива, чтобы сохранить ее в:

var balance = loanAmount
//array of monthly balances, with the initial loan amount to start with:
var monthlyBalances = [balance]
for i in 1...360 {
    let interestPayment = balance * r
    let principalPayment = monthlyPayment - interestPayment

    balance -= principalPayment
    monthlyBalances.append(balance)
}

Продвинутая версия для тех, кто заинтересован

Вы можете спросить, есть ли способ объявить monthlyBalances с let скорее, чем var, И есть! Вы могли бы использовать reduce:

let monthlyBalances = reduce(1...360, [loanAmount]) { 
  payments, _ in
    let balance = payments.last!
    let interestPayment = balance * r
    let principalPayment = monthlyPayment - interestPayment

    return payments + [balance - principalPayment]
}

Однако это несколько неприятно по нескольким причинам. Было бы намного приятнее, если бы в стандартной библиотеке Swift была немного другая версия Reduction, называемая accumulate который сгенерировал массив из промежуточной суммы, например так:

let monthlyBalances = accumulate(1...360, loanAmount) { 
  balance, _ in
    let interestPayment = balance * r
    let principalPayment = monthlyPayment - interestPayment

    return balance - principalPayment
}

И вот определение accumulate:

func accumulate<S: SequenceType, U>
  (source: S, var initial: U, combine: (U, S.Generator.Element) -> U)
   -> [U] {
        var result: [U] = []
        result.append(initial)
        for x in source {
            initial = combine(initial, x)
            result.append(initial)
        }
        return result
}
Другие вопросы по тегам