代码改变世界

求一个等差数列

2017-01-19 22:20 stoneniqiu 阅读(...) 评论(...) 编辑 收藏

需要要一个金额递减的效果,最终的效果如下,这其实就是一个等差数列。

我们学过的等差数列求和公式是:

也就是首末相加乘以N再除以2.而我们得到的参数是总金额和总人数,求整个数列。我们默认最小的差值是0.01,也就是一分钱,首项是a0,那么aN=a0+(n-1)*gap代码如下:

 private decimal[] GetDeclines(decimal reward, int people, decimal min)
        {
            //需要验证min 和 gap
            //min不能大于平均值。gap可以是0,
            //求和公式 2*reward=(a0+ak)*n       k=n-1
            //people只有一人
            if (people == 1)
                return new[] { reward };
            //min等于平均值
            if (min == (reward / people) && ((int)reward * 100 % people == 0)) return GetAverages(reward, people);

            var a_0a_n = 2 * reward / people;//得到首末两项的和
            var gap_n_1 = a_0a_n - 2 * min;//得到peple-1个间距的值
            var gap100 = (int)(gap_n_1 / (people - 1) * 100);//放大一百倍 确保小数
            var gap = (decimal)gap100 / 100;
            var results = new decimal[people];
        //然后逐个求出每一项的值。
            for (int i = 0; i < people; i++)
            {
                results[i] = min + gap * (people - i - 1);
            }
            
            var sum = people * (results[0] + results[people - 1]) / 2;
            var more = reward - sum;
            results[0] = results[0] + more;

            return results;
        }

关键是通过min计算出差额gap,而这个差值我们可以默认的设置为总金额的五十分之一。

if (model.Reward >=1)
{
  model.MinReward = model.Reward / 50;
}

金额不可能每次被完全分掉,这里是将多出的金额加到了的第一项里面。

 

你会发现剩余金额其实不会随着总金额变大而变大,居然是一样的。有点意思。console代码如下:

class Program
    {
        static void Main(string[] args)
        {
            GetDeclines(1000, 10);
            Console.Read();
        }

        private static decimal[] GetDeclines(decimal reward, int people)
        {
            var min=(decimal)0.01;
            if (reward > 1)
            {
                min = reward/50;
            }

            //需要验证min 和 gap
            //min不能大于平均值。gap可以是0,  
            //求和公式 2*reward=(a0+ak)*n       k=n-1
            //people只有一人
            if (people == 1)
                return new[] { reward };
            //min等于平均值
            if (min == (reward / people) && ((int)reward * 100 % people == 0)) return GetAverages(reward, people);
            var a_0a_n = 2 * reward / people;
            var gap_n_1 = a_0a_n - 2 * min;
            var gap100 = (int)(gap_n_1 / (people - 1) * 100);
            var gap = (decimal)gap100 / 100;
            var results = new decimal[people];
            Console.WriteLine("总金额{0},最小值{1},{2}个人,差额{3}", reward, min, people,gap);

            for (int i = 0; i < people; i++)
            {
                results[i] = min + gap * (people - i - 1);
                Console.WriteLine("第{0}项:{1}",i,results[i]);
            }

            var sum = people * (results[0] + results[people - 1]) / 2;
            var more = reward - sum;
            Console.WriteLine("剩余"+more);
            results[0] = results[0] + more;

            return results;
        }

        private static decimal[] GetAverages(decimal reward, int people)
        {
            var per = reward / people;
            var ds = new decimal[people];
            for (int i = 0; i < people; i++)
            {
                ds[i] = per;
            }
            return ds;
        }

    }
View Code