费用分摊问题

在现实生活中,我们可能会遇到这样的问题:三个人合伙买一件商品,假如这件商品的价格为1。三个人平摊的费用为1/3,可以用分数表示,但是计算机处理最后的结果是小数0.33(保留两位小数),这样0.33*3=0.99<1,于是就必须有一个人要付0.34。所以在处理费用分摊问题时,并不是每人承担的费用都是总费用*平摊的百分比,对于1/5,2/5,2/5这样的比例算出的结果是没有问题的。总之,要确保分摊的费用之和等于总费用,采取前两个人分别承担的费用=总费用*百分比,最后一个人承担的费用=总费用-(前两个人承担的费用之和)这样的方法就没有问题了。概括的说,前面的费用(除最后一个的费用)都采用总费用*百分比的方法,而最后一个采用(总费用-前面的费用之和)的方法,这样就确保了分摊的费用与总费用没有误差。

      虽然前面的方法是解决了费用分摊的问题,但那方法只是一组费用分摊的问题,但多组费用分摊放到一起的时候,每组的总价不一样,百分比,怎么解决?少量的数据,人的肉眼还可以区分哪些Item是一组,但是大量数据出现时,又怎样处理呢?为了更好理解,我列举数据和编写程式。

No GW TotalGW Fee
12.32.3 
213 
21.23 
20.83 
32.22.4 
30.22.4 
43.43.4 
53.53.5 

       首先,我们将数据安照No分组排序;其次,如果按重量分摊的话,多个item分摊的总重TotalGW是不变的,而每组的GW的之和等于每组的TotalGW,这样分摊的百分比就是GW/TotalGW。No号不重复的,费用承担百分比=GW/TotalGW=100%,也就是承担全部费用;最后强调一点,每组的总费用都不相同,但是通过每组的No可以找到对应的总费用,1--->x,2--->y,3--->Z等,同一组的总费用是相同的。

      因为每组的总费用不一样,就要有个标志变量区分组别;总费用变量存对应组的总费用,用于按照百分比*总费用计算分摊费用; 剩余费用变量,用于求分摊组最后一行的费用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public  DataTable Calculate(DataTable dt)
  {
      string  groupNo = "" ; //组号标志变量
      string  no; //DataTable中的DataRow的No
      decimal  totalFee = 0.00m; //总费用
      decimal  remaining = 0.00m; //剩余费用,用于求一组中最后一行的分摊费用
      for  ( int  i = 0; i < dt.Rows.Count; i++)
      {
          no = dt.Rows[i][ "No" ].ToString();              
          if  (groupNo != no) //这一行跟上一行的No进行比较,判断是否是同一组别
          {<br>                    //不同组的处理办法
              if  (i != 0)
              {
                  dt.Rows[i - 1][ "Fee" ] = remaining + Convert.ToDecimal(dt.Rows[i - 1][ "Fee" ]); //重新为上一行的fee赋值,因为上一行是上一组的最后一行,分摊                                                                                                 费用=总费用-同组下的前面分摊费用之和
              }
              groupNo = no; //改变标志组号变量,进行下次比较
              totalFee = GetTotalFee(no); //获取该组对应的总费用
              remaining = totalFee; //初始化剩余费用
          }
          dt.Rows[i][ "Fee" ] = totalFee * Convert.ToDecimal(dt.Rows[i][ "GW" ]) / Convert.ToDecimal(dt.Rows[i][ "TotalGW" ]); //按照百分比*总费用求分摊费用
          remaining -= Convert.ToDecimal(dt.Rows[i][ "Fee" ]); //更新剩余费用
     
    if (dt.Rows.Count>2)        
    {
        dt.Rows[dt.Rows.Count-1][ "Fee" ]=remaining+Convert.ToDecimal(dt.Rows[dt.Rows.Count-1][ "Fee" ]); //防止最后一行与前一行同组,重新赋值
     }           
      return  dt;
  }
 
  public  decimal  GetTotalFee( string  no)
  {
       return  12.0m;   //返回每组对应的总费用       
  }

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值