C# red envelope fluctuation coefficient·high availability, suitable for enterprise-level development

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace testDemo1
{     /// <summary>     /// Red envelope algorithm, the fluctuation ratio is between 0-1     /// </summary>     class Program     {




        static void Main(string[] args) {             Program p = new Program();             //When allocating the amount, be sure to pay attention to the reasonable planning of the total amount, the amount distributed and the maximum amount             List<decimal> lists = p.createBonusList(500,500,decimal .Parse("0.01"),10,decimal.Parse("0.5"));             decimal Count = 0;             foreach (var item in lists)             {                 Count += item;                 Console.WriteLine(item);             }             Console.WriteLine( "Total:"+Count);         }










        Random ra = new Random();

        /// <summary>
        /// Generate a red envelope one-time distribution result·Main method entry
        /// </summary>
        /// <param name="totalBonus">totalBonus</param>
        /// <param name="totalNum ">totalNum</param>
        /// <param name="rdMin"></param>
        /// <param name="rdMax"></param>
        /// <param name="bigRate">specify big Probability of range interval</param>
        /// <returns></returns>
        public List<decimal> createBonusList(decimal totalBonus, decimal totalNum, decimal rdMin, decimal rdMax, decimal bigRate)
        {             decimal sendedBonus = 0;             decimal sendedNum = 0 ;             List<decimal> bonusList = new List<decimal>();             while (sendedNum < totalNum)




            {
                decimal bonus = randomBonusWithSpecifyBound(totalBonus, totalNum, sendedBonus, sendedNum, rdMin, rdMax, bigRate);
                bonus = Convert.ToDecimal(bonus.ToString("#0.00"));
                bonusList.Add(bonus);
                sendedNum++;
                sendedBonus += bonus;
            }
            return bonusList;
        }


        /// <summary>
        /// 随机分配第n个红包
        /// </summary>
        /// <param name="totalBonus"></param>
        /// <param name="totalNum"></param>
        /// <param name="sendedBonus"></param>
        /// <param name="sendedNum"></param>
        /// <param name="rdMin"></param>
        /// <param name="rdMax"></param>
        /// <param name="bigRate">平衡度0-1</param>
        /// <returns></returns>
        private decimal randomBonusWithSpecifyBound(decimal totalBonus, decimal totalNum, decimal sendedBonus,
        decimal sendedNum, decimal rdMin, decimal rdMax, decimal bigRate)
        {
            decimal avg = totalBonus / totalNum; // mean
            decimal leftLen = avg --rdMin;
            decimal rightLen = rdMax --avg;
            decimal boundMin = 0, boundMax = 0;

            // Set a small probability in a large range
            if (leftLen.Equals(rightLen))
            {                 boundMin = Math.Max((totalBonus-sendedBonus-(totalNum-sendedNum-1) * rdMax), rdMin);                 boundMax = Math.Min((totalBonus -sendedBonus-(totalNum-sendedNum-1) * rdMin), rdMax);             }             else if (rightLen.CompareTo(leftLen)> 0)             {                 // upper limit deviation                 decimal standardRdMax = avg + leftLen; // right symmetric upper limit point                 decimal _rdMax = canReward(bigRate)? rdMax: standardRdMax;                 boundMin = Math.Max((totalBonus-sendedBonus-(totalNum-sendedNum-1) * standardRdMax), rdMin);









                boundMax = Math.Min((totalBonus - sendedBonus - (totalNum - sendedNum - 1) * rdMin), _rdMax);
            }
            else
            {
                // 下限偏离
                decimal standardRdMin = avg - rightLen;  // 左侧对称下限点
                decimal _rdMin = canReward(bigRate) ? rdMin : standardRdMin;
                boundMin = Math.Max((totalBonus - sendedBonus - (totalNum - sendedNum - 1) * rdMax), _rdMin);
                boundMax = Math.Min((totalBonus - sendedBonus - (totalNum - sendedNum - 1) * standardRdMin), rdMax);
            }

            // sent average offset correction-dynamic scale
            if (boundMin.Equals(boundMax))
            {                 return getRandomVal(boundMin, boundMax);             }             decimal currAvg = sendedNum == 0? Avg: (sendedBonus / sendedNum); // current Sent average             decimal middle = (boundMin + boundMax) / Convert.ToDecimal(2.0);             decimal subMin = boundMin, subMax = boundMax;             // expected value              decimal exp = avg-(currAvg-avg) * sendedNum / (totalNum-sendedNum) ;             if (middle> exp)             {                 subMax = Math.Round((boundMin + exp) / Convert.ToDecimal(2.0));             }             else












            {
                subMin = Math.Round((exp + boundMax) / Convert.ToDecimal(2.0));
            }
            decimal expBound = (boundMin + boundMax) / 2;
            decimal expSub = (subMin + subMax) / 2;
            decimal subRate = (exp - expBound) / (expSub - expBound);
            return getRandomValWithSpecifySubRate(boundMin, boundMax, subMin, subMax, subRate);
        }


        /// <summary>
        /// 下限随机
        /// </summary>
        /// <param name="rate"></param>
        /// <returns></returns>
        private bool canReward(decimal rate)
        {
            return Convert.ToDecimal(ra.NextDouble().ToString()) <= rate;
        }

        /**
         * Return a random number in the min~max range, including min and max
         * @param min
         * @param max
         * @return
         */
        private decimal getRandomVal(decimal min, decimal max)
        {             decimal v = Convert.ToDecimal(ra. NextDouble()) * max;             v = Convert.ToDecimal(v.ToString("#0.00"));             return v >= min? V: min;         }



        /// <summary>
        /// Random algorithm with probability bias, the probability bias in the subMin~subMax interval returns a random number in the boundMin~boundMax interval (including boundMin and boundMax), and at the same time, you can specify the priority probability of subMin~subMax. Example: Pass in the parameters (10, 50, 20, 30, 0.8), and the random result will be returned randomly from 20 to 30 with 80% probability, and randomly returned from 10 to 50 with 20% probability
        /// </summary>
        // / <param name="boundMin"></param>
        /// <param name="boundMax"></param>
        /// <param name="subMin"></param>
        /// <param name= "subMax"></param>
        /// <param name="subRate"></param>
        /// <returns></returns>
        private decimal getRandomValWithSpecifySubRate(decimal boundMin, decimal boundMax, decimal subMin, decimal subMax,decimal subRate)
        {             if (canReward(subRate))             {


                return getRandomVal(subMin, subMax);
            }
            return getRandomVal(boundMin, boundMax);
        }
    }
}

Guess you like

Origin blog.csdn.net/feng8403000/article/details/104324012