Skip to main content
 首页 » 操作系统

ios之在 Swift 中为摊销计划创建循环

2024年01月01日60qlqwjy

我想找出一个简单的循环来计算 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 
} 

希望生成月度计划。预先感谢您提供任何提示。

请您参考如下方法:

我猜你的意思是在循环外声明 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 – 但这是一个整体 other question)。

如果你想创建每月余额,比如在一个数组中,你可以添加一个额外的数组变量来存储它:

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) 
} 

适合任何感兴趣的人的高级版本

您可能想知道是否有一种方法可以使用 let 而不是 var 来声明 monthlyBalances。有!您可以使用 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 标准库有一个略有不同的称为 accumulate 的 reduce 版本,它会从运行总计中生成一个数组,就像这样:

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 
}