Vb.net 如何防止循环贷款系统中出现类似的十进制问题

Vb.net 如何防止循环贷款系统中出现类似的十进制问题,vb.net,Vb.net,我总是在循环的第三个条目中得到错误的小数。如果我使用计算器,我会得到正确的结果,但如果我把它放在excel中,我会得到错误的十进制结果。我想要的是在excel和我的系统中得到相同的结果 比如说 我尝试使用Decimal.Round(值,2)。它解决了第二个条目的舍入问题,但下一个问题出现在第三个条目中。我看到了主体:773192.13。我应该看到773192.12,因为这是Excel中的结果,因为它对本金进行了四舍五入,所以余额中的结果增加了 这是Excel中的结果。你会注意到我放了一些+1,-

我总是在循环的第三个条目中得到错误的小数。如果我使用计算器,我会得到正确的结果,但如果我把它放在excel中,我会得到错误的十进制结果。我想要的是在excel和我的系统中得到相同的结果

比如说

我尝试使用
Decimal.Round(值,2)
。它解决了第二个条目的舍入问题,但下一个问题出现在第三个条目中。我看到了
主体:773192.13
。我应该看到
773192.12
,因为这是Excel中的结果,因为它对本金进行了四舍五入,所以余额中的结果增加了

这是Excel中的结果。你会注意到我放了一些
+1
-1
,或者
-2
。这就是我系统中的结果,它不断地进行减法或加法。我的余额中有
-0.05
作为最终结果

Excel结果
我将关注第三行的主要值。听起来您想在此处查看
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
注意额外的小数点(
.001
在第2行,
.004
在第3行)。如果您在将其从每月摊销中删除之前没有进行取整,那么您最终会得到分数美分作为计算本金的一部分,然后是余额。到第三个结果时,它总共是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
上面的代码还解决了一些其他问题,即在处理货币时,您应该始终使用
十进制
,而不是
双精度


唯一的例外是,如果这里的合同规定,分数利息应始终向上取整,以有利于银行

可能的重复项有一个简单的解释,说明如何将双倍存储在十进制中,可能会产生更好的结果。我已经试着使用As Decimal,我得到了同样的结果如果你知道并尝试了
Decimal
类型,那就意味着你知道对任何涉及金钱的事情使用
Double
是错误的。你为什么要在这里发布显示为双精度的代码?Joel Coehoorn抱歉,我在发布之前忘了更改它,我已经尝试使用十进制,但是我得到了错误的结果。小数点不停地进行减法运算adding@aijomsaugmata评论不能有某些格式化的项目。请重新发布。这是~Dim minterest的结果,十进制=数学四舍五入(余额*(利率/12D),2)利息:128000.00本金:765517.81余额:24834482.19利息:124172.41本金:769345.40余额:24065136.79利息:120325.68本金:773192.13余额:23291944.66利息:116459.72本金:777058.09余额:22514886.57利息:112574.43本金:780943.38余额:21733943.19利息:108669.72本金:784848.09余额:20949095。10@aijomsaugmata是的,这是正确的结果。Excel结果是错误的。您可以在Excel的第三行清楚地看到这一点,因为893517.81-120325.68=773192.13,而不是773192.12。你甚至不需要计算器来检查它。请看分钱部分:81-68=13,而不是12。@aijomsaugmata请务必阅读我的完整答案。现在那里的信息比第一次发布时更多。@aijomsaugmata不在注释中发布代码或数据。没有空间,也无法格式化。如果您有新信息,请更新原始问题。
minterest = Math.Round((balance * (interestrate / 12)),2)
128000.0000 
124172.4110 
120325.6840
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