精确增值税计算的十进制舍入问题

时间:2015-07-20 23:08:31

标签: c#

是否有更专业的方式呈现以下冗长,错综复杂的尝试提取净值并确定增值税金额,以便所有等于起始总数(tot1)

            decimal tot1 = Convert.ToDecimal(typeA) + Convert.ToDecimal(typeB);
            decimal netTot = Math.Round(Convert.ToDecimal(tot1) / 1.2m, 2);
            decimal vat = tot1 - netTot;
            decimal netA = Math.Round(Convert.ToDecimal(typeA) / 1.2m, 2);
            decimal netB = Math.Round(Convert.ToDecimal(typeB) / 1.2m, 2);
            decimal netAA = netTot - (netA + netB);
            decimal netAAA = netAA + netA;

话虽如此,这个代码适用于10个案例中的9个。有时会有正负0.01差异,我不明白为什么

2 个答案:

答案 0 :(得分:1)

在操作过程中停止四舍五入,只绕过你得到的最终数字。你得到的问题是当你得到像0.333333之类的数字并在继续数学之前将其四舍五入,在我的例子中,这会丢掉1/3的分数。

好的,这是一个例子,让我们假设出于某种原因你得到这些值:

typeA = 39.5
typeB = 0.5

它总计为40.所以netTot((typeA + typeB)/1.2)将是:

33,333333333333333333333333333333

之后,你把它四舍五入到33.33。 然后,netA(typeA / 1.2)和netB(typeB / 1.2)将是:

netA = 32,916666666666666666666666666667
netB = 0,41666666666666666666666666666667

您将每个分别舍入为32.92和0.42,总计为33,34,与netTot的舍入为33.33不同。

正如你所看到的,你绕过的netA和netB的总和会搞砸数学。

答案 1 :(得分:0)

对值进行舍入有两个原因。

  1. 用于显示目的 - 当您计算了一个值,但现在想要显示它。
  2. 出于法律目的 - 当法律规定增值税四舍五入到最接近的分数/便士等时。
  3. 除非上述两种情况之一适用,否则不应在执行计算时进行舍入。

    您可能想要检查增值税是否应四舍五入到最接近的分数/便士,或者是否应该仅向上舍入。在澳大利亚,商品及服务税必须四舍五入至最接近的分数,因为政府不想错过这些分数!

    我会假设你需要围捕。因此,我不会执行Math.Round(total / 1.2m, 2)(获取网络),而是Math.Ceiling(total * 100m / 6m) / 100m(获取增值税)。

    所以,说过你最终会遇到一个潜在的问题,试图像这样打破你的数字。

    比如说你的输入是typeA = "10.47"& typeB = "15.27"然后计算增值税总额将是:

    var a_vat = Math.Ceiling(a_tot * 100m / 6m) / 100m;
    var a_net = a_tot - a_vat;
    
    var b_vat = Math.Ceiling(b_tot * 100m / 6m) / 100m;
    var b_net = b_tot - b_vat;
    

    给出了:

    a: 8.72 + 1.75 = 10.47
    b: 12.72 + 2.55 = 15.27
    

    两者都很好。

    但是尝试聚合它们就可以了:

    var ab_tot = a_tot + b_tot;
    
    var ab_vat = Math.Ceiling(ab_tot * 100m / 6m) / 100m;
    var ab_net = ab_tot - ab_vat;
    
    21.45 + 4.29 = 25.74
    

    您应该注意10.47 + 15.27 = 25.74(所以总计加起来),但a&的单独增值税。 b 加起来a + b的增值税总额。

    1.75 + 2.55 = 4.30 != 4.29
    

    所以,由于对这样的总数进行任何类型的舍入,你会得到像这样的错误。你无法避免它们。

    有两种方法可以解决这个问题。

    1. 您可以从包含增值税的单个价格开始,然后通过添加每个组件的增值税来计算总增值税。

    2. 或者,您从不包含增值税的单个价格开始,并在最终总计上计算一次增值税。

    3. 因此,就我的例子而言,我会做这组计算:

      var a_vat = Math.Ceiling(a_tot * 100m / 6m) / 100m;
      var b_vat = Math.Ceiling(b_tot * 100m / 6m) / 100m;
      
      var ab_vat = a_vat + b_vat;
      
      var ab_tot = a_tot + b_tot;
      
      var ab_net = ab_tot - ab_vat;