计算百分比分布中的下一个项目
我正在开展一个项目,涉及将电话转移到多个目的地。
例如,我想:
- 10%的电话到达目的地A.
- 20%的电话前往目的地B.
- 30%的电话转到目的地C.
- 40%的电话前往目的地D.
目的地数量及其百分比必须是可配置的。
我一直在考虑如何做到这一点,玩电子表格和一些代码,我想出了这个:
对于每个目的地,取一个随机数,乘以百分比,然后选择编号最大的目的地。 像这样:
Item: RANDOM * PERCENTAGE = RESULT A: 48 * 10 = 480 B: 33 * 20 = 660 C: 81 * 30 = 2430 <--- Highest number, select C D: 5 * 40 = 200
我以为我已经解决了,因为D显然会被选中最多,其次是C,然后是B,最不是A.
但它不起作用。 如果我这样做5000次,并计算每个目的地被选中的实际百分比,我得到这个:
- 1%的电话前往目的地A.
- 12%的电话前往目的地B.
- 31%的电话转到目的地C.
- 56%的电话到达目的地D.
这是我用来测试这个的代码:
// Initialise item weighting percentages Dictionary weighting = new Dictionary(); weighting["A"] = 10; //10% weighting["B"] = 20; //20% weighting["C"] = 30; //30% weighting["D"] = 40; //40% (total = 100%) // Initialise data set used for each iteration Dictionary data = new Dictionary(); // Initialise counts of the selected items Dictionary count = new Dictionary(); count["A"] = 0; count["B"] = 0; count["C"] = 0; count["D"] = 0; Random rand = new Random(); // Loop 5000 times for (int i = 0; i x.Value == data.Max(y => y.Value)).Key; count[sel]++; // Log, so you can see whats going on... if (i z.Value))); Console.WriteLine(" B = {0}%", 100 * ((double)count["B"] / (double)count.Sum(z => z.Value))); Console.WriteLine(" C = {0}%", 100 * ((double)count["C"] / (double)count.Sum(z => z.Value))); Console.WriteLine(" D = {0}%", 100 * ((double)count["D"] / (double)count.Sum(z => z.Value)));
结果是:
A:00780 B:00300 C:01740 D:03680 SELECTED:D A:00600 B:00660 C:00060 D:03400 SELECTED:D A:00900 B:01880 C:00510 D:00720 SELECTED:B A:00260 B:01380 C:00540 D:01520 SELECTED:D A:00220 B:01960 C:00210 D:02080 SELECTED:D A:00020 B:01400 C:01530 D:00120 SELECTED:C A:00980 B:00400 C:01560 D:03280 SELECTED:D A:00330 B:00300 C:01500 D:03680 SELECTED:D A:00590 B:00460 C:02730 D:02400 SELECTED:C A:00580 B:01900 C:02040 D:01320 SELECTED:C A:00620 B:01320 C:00750 D:01760 SELECTED:D A:00320 B:01040 C:01350 D:03640 SELECTED:D A:00340 B:01520 C:02010 D:03880 SELECTED:D A:00850 B:01420 C:00480 D:03400 SELECTED:D A:00560 B:00680 C:00030 D:00000 SELECTED:B ... Results: A = 1.44% B = 11.54% C = 30.6% D = 56.42%
任何人都可以建议一种方法来解决这个问题,以便真正的百分比按配置出来吗?
对于奖励积分,任何人都可以建议一种类似但不使用随机数的方法,以便明确定义所选目的地的顺序。 使用上面的示例每次都会输出此序列:
ABCDBCDCDD ABCDBCDCDD ABCDBCDCDD ABCDBCDCDD ...
(注意序列均匀分布)
谢谢。 本
好吧,我之前已经在模拟中做了很多次,所以这里是我使用的基本方法(没有正确的错误检查):
你需要想象一下整个页面的线条画从0到100.现在我们正在做的是在你的目的地之间按比例划分这条线。 然后我们使用随机数在这一行上选择一个点。 具有该区域的目的地是所选择的那个。
编辑:尝试线图
|-----------------------------------------------------| Line 1 to 100 |-----|----------|---------------|--------------------| Line split proportionally 0 A 10 B 30 C 60 D 100
我们可以这样做。
假设您的目标百分比在数组中,而不是在单独的变量中。
int totalPercentages = 0; int destinationsIndex = -1; int randomNumberBetween0and100 = GetRandomNumber(); for(int i = 0; i < destinationPercentageArrays.Length; i++) { totalPercentages += destinationPercentageArrays[i]; if (totalPercentages > randomNumberBetween0and100) { destinationIndex = i; break; } } if (destinationIndex == -1) { throw new Exception("Something went badly wrong."); }
现在,变量destinationIndex
指向所选目标。
按照您给出的百分比进行分配:
创建1到100之间的随机数(包括)
If < 10 A If > 10 < 30 B If > 30 < 60 C If > 60 D
至于如何定义列表的问题,只需将目的地按顺序放入一个数组中,并一次一个地枚举它们。 当你用完时,从头开始。
string[] destinations = new string[] { "A", "B", "C", "D", ... } int counter = 0; //when need routing RouteTo(destinations[counter]); counter++; if (counter == destinations.Length) { counter = 0; }
另一种可能性是使用for循环填充大小为100的列表,并插入每个值乘以其权重。 然后随机选择一个列表项。
示例,短名单(10项)
- 5x A.
- 4x B.
- 1x C.
列表= {A,A,A,A,A,B,B,B,B,C}
随机介于0到9之间。
这将创建一个100个字符长的随机列表,即ABCDBCDCDD ……
static void Main() { var weighting = new Dictionary(); weighting['A'] = 10; //10% weighting['B'] = 20; //20% weighting['C'] = 30; //30% weighting['D'] = 40; //40% (total = 100%) var test = CreateOrder(weighting); } static IEnumerable CreateOrder(Dictionary weighting) { var list = new List>(); var random = new Random(); foreach (var i in weighting) { for (int j = 0; j < i.Value; j++) { list.Add(new KeyValuePair(random.Next(), i.Key)); } } return list.OrderBy(u=>u.Key).Select(u => u.Value); }