如何在我的循环贷款系统中预防像这样的小数问题

时间:2018-12-29 04:10:26

标签: vb.net

我总是在循环的第三项中输入错误的小数。如果使用计算器,则得到正确的结果,但是如果将其放在excel中,则以十进制表示的结果是错误的。我想要在excel和我的系统中得到相同的结果。

例如。

我尝试使用Decimal.Round(value,2)。它解决了第二个条目从四舍五入的问题,但是下一个问题出现在第三个条目中。我看到Principal: 773192.13。我应该看到773192.12,因为这是Excel中的结果,并且因为它是为委托人舍入的,所以余额中的结果会增加。

这是Excel中的结果。您会注意到我放了一些+1-1-2。那就是我的系统不断减少或增加的结果。我的余额中有-0.05作为最终结果。

Excel结果

Principal: 765517.81 Interest: 128000.00 Balance: 24834482.19 
Principal: 769345.40 Interest: 124172.41 Balance: 24065136.79 
Principal: 773192.12 Interest: 120325.68 Balance: 23291944.67 
Principal: 777058.09 Interest: 116459.72 Balance: 22514886.58 
Principal: 780943.38 Interest: 112574.43 Balance: 21733943.21 
Principal: 780943.09 Interest: 108669.72 Balance: 20949095.12 

系统结果

Principal: 765517.81      Interest: 128000.00   Balance: 24834482.19 
Principal: 769345.40      Interest: 124172.41   Balance: 24065136.79 
Principal: 773192.13 +1     Interest: 120325.68   Balance: 23291944.66 -1
Principal: 777058.09      Interest: 116459.72   Balance: 22514886.57 -1 
Principal: 780943.38      Interest: 112574.43   Balance: 21733943.19 -2 
Principal: 784848.09      Interest: 108669.72   Balance: 20949095.11 -1    

我的代码

Dim balance As Decimal= 25600000
Dim pmtmonthlyamortization As Decimal= 893517.81
Dim interestrate As Decimal= 6.0 / 100
Dim TotPmts As Double
Dim mprincipal As Decimal
Dim minterest As Decimal

TotPmts = CDbl(Val(5))

For i = 0 To TotPmts
    minterest = (balance * (interestrate / 12))
    mprincipal = (pmtmonthlyamortization - minterest)
    balance = (balance - mprincipal)

    MessageBox.Show(minterest & vbNewLine & mprincipal & vbNewLine & vbNewLine & balance)
Next 

1 个答案:

答案 0 :(得分:2)

我将重点关注第三行的Principal值。听起来好像您想在这里看到773192.12,以便与Excel计算匹配。但是, Excel计算错误! 773192.13是正确的数字,尽管程序本身仍需要一些工作,但程序的结果已经正确了。

原因是您无法收取小数利息。在计算利息时,必须四舍五入,在将利息费用应用于摊销之前。因此,我们更改了这一行:

minterest = (balance * (interestrate / 12))

对此:

minterest = Math.Round((balance * (interestrate / 12)),2)

此外,在Excel计算中进行相同的更改,因此在将其利息从摊销额中扣除之前将其四舍五入。

现在,对于773192.13,我们得到了非常明确的结果。我们可以通过检查前三行的全部利息计算来看到这一点,如下所示:

128000.0000 
124172.4110 
120325.6840

请注意额外的分数(第2行的.001,第3行的.004)。如果您不进行之前的舍入,将其从每月摊销中删除,最终将得到小数分作为计算的本金的一部分,然后余额。到第三个结果时,总计为1/2便士,足以显示在屏幕上。

您也可以轻松证明这一点,因为893517.81-120325.68 = 773192.13,而不是773192.12。如果您只看数字的美分部分,就可以用头脑证明它,甚至不用计算器:81 - 68 = 13显然是正确的答案。

将来,如果在确定计算正确之前将结果显示到4位,这种事情将更易于调试。下面的代码使您可以同时使用两种方法:

Dim balance As Decimal = 25600000D
Dim pmtmonthlyamortization As Decimal = 893517.81D
Dim interestrate As Decimal = 6.0D / 100D
Dim TotPmts As Integer = 5

For i As Integer = 0 To TotPmts
    'Pick one line below at a time to un-comment so you can see the results when run both ways:
    'Dim minterest As Decimal = Math.Round(balance * (interestrate / 12D), 2)
    'Dim minterest As Decimal = balance * (interestrate / 12D)
    mprincipal = pmtmonthlyamortization - minterest
    balance -= mprincipal

    MessageBox.Show($"Principle: {mprincipal:F4} Interest: {minterest:F4} Balance: {balance:F4}")
Next

上面的代码还解决了其他一些问题,即您在赚钱时应始终使用Decimal而不是Double

一个例外是,如果这里的合同规定小数利息应始终凑整以利于银行