计算百分比分布中的下一个项目
我正在开展一个项目,该项目涉及将电话转移到多个目的地。
例如,我希望:
- 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<string, int> weighting = new Dictionary<string, int>();
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<string, int> data = new Dictionary<string, int>();
// Initialise counts of the selected items
Dictionary<string, int> count = new Dictionary<string, int>();
count["A"] = 0;
count["B"] = 0;
count["C"] = 0;
count["D"] = 0;
Random rand = new Random();
// Loop 5000 times
for (int i = 0; i < 5000; i++) {
// For each item, get a random number between 0 and 99
// and multiply it by the percentage to get a
// weighted random number.
data["A"] = rand.Next(100) * weighting["A"];
data["B"] = rand.Next(100) * weighting["B"];
data["C"] = rand.Next(100) * weighting["C"];
data["D"] = rand.Next(100) * weighting["D"];
// Find which item came out on top and increment the count
string sel = data.First(x => x.Value == data.Max(y => y.Value)).Key;
count[sel]++;
// Log, so you can see whats going on...
if (i < 15)
Console.WriteLine("A:{0:00000} B:{1:00000} C:{2:00000} D:{3:00000} SELECTED:{4}",
data["A"], data["B"], data["C"], data["D"], sel);
else if (i == 15) Console.WriteLine("...");
}
// Output the results, showing the percentage of the number
// occurrances of each item.
Console.WriteLine();
Console.WriteLine("Results: ");
Console.WriteLine(" A = {0}%", 100 * ((double)count["A"] / (double)count.Sum(z => 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 ...
注意序列是均匀分布的)
谢谢。 本
I'm working on a project that involves diverting phone calls to a number of destinations.
For example, I want:
- 10% of calls to go to destination A
- 20% of calls to go to destination B
- 30% of calls to go to destination C
- 40% of calls to go to destination D
The number of destinations and their percentages must be configurable.
I've been thinking about how to do this, playing around with spreadsheets and some code, and I came up with this:
For each destination, take a random number, multiply it by the percentage, and select the destination with the highest number. Like this:
Item: RANDOM * PERCENTAGE = RESULT
A: 48 * 10 = 480
B: 33 * 20 = 660
C: 81 * 30 = 2430 <--- Highest number, select C
D: 5 * 40 = 200
I thought I'd worked it out as D would clearly be selected the most, followed by C, then B, and least of all A.
But it doesn't work. If I do this 5000 times, and calculate the actual percentage of times each destination was selected, I get this:
- 1% of calls to go to destination A
- 12% of calls to go to destination B
- 31% of calls to go to destination C
- 56% of calls to go to destination D
Here is the code I used to test this:
// Initialise item weighting percentages
Dictionary<string, int> weighting = new Dictionary<string, int>();
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<string, int> data = new Dictionary<string, int>();
// Initialise counts of the selected items
Dictionary<string, int> count = new Dictionary<string, int>();
count["A"] = 0;
count["B"] = 0;
count["C"] = 0;
count["D"] = 0;
Random rand = new Random();
// Loop 5000 times
for (int i = 0; i < 5000; i++) {
// For each item, get a random number between 0 and 99
// and multiply it by the percentage to get a
// weighted random number.
data["A"] = rand.Next(100) * weighting["A"];
data["B"] = rand.Next(100) * weighting["B"];
data["C"] = rand.Next(100) * weighting["C"];
data["D"] = rand.Next(100) * weighting["D"];
// Find which item came out on top and increment the count
string sel = data.First(x => x.Value == data.Max(y => y.Value)).Key;
count[sel]++;
// Log, so you can see whats going on...
if (i < 15)
Console.WriteLine("A:{0:00000} B:{1:00000} C:{2:00000} D:{3:00000} SELECTED:{4}",
data["A"], data["B"], data["C"], data["D"], sel);
else if (i == 15) Console.WriteLine("...");
}
// Output the results, showing the percentage of the number
// occurrances of each item.
Console.WriteLine();
Console.WriteLine("Results: ");
Console.WriteLine(" A = {0}%", 100 * ((double)count["A"] / (double)count.Sum(z => 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)));
The results are:
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%
Can anyone suggest a way to fix this so that the real percentages come out as configured?
And for bonus points, can anyone suggest a way to do something similar but not using random numbers, so that the sequence of selected destinations is clearly defined. Using the example above would output this sequence every time:
ABCDBCDCDD ABCDBCDCDD ABCDBCDCDD ABCDBCDCDD ...
(note that the sequence is evenly distributed)
Thanks.
Ben
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
好吧,我之前在模拟中已经做过很多次了,所以这是我使用的基本方法(没有适当的错误检查):
你需要想象在页面上从 0 到 100 画一条线。现在我们要做的是除以该队列按您的目的地的比例排列。然后我们使用随机数来选择这条线上的一个点。具有该线路区域的目的地即为所选目的地。
编辑:尝试折线图
我们可以按如下方式执行此操作。
假设您的目标百分比位于数组中,而不是单独的变量中。
现在变量
destinationIndex
指向选定的目的地。Ok, I have done this numerous times before in simulations so here is the basic method I use (without proper error checking):
You need to imagine a line draw across the page going from 0 to 100. Now what we're doing is dividing this line up proportionally amongst your destinations. We then use random numbers to choose a point on this line. The destination which has that area of the line is the one selected.
EDIT: Attempt at line diagram
We can do this as follows.
Assume your destination percentages are in an array, instead of in separate variables.
Now the variable
destinationIndex
points to the selected destination.对于按您给出的百分比进行的分布,请执行以下操作:
创建一个 1 到 100(含)之间的随机数
至于如何定义列表的问题,只需将目的地按顺序放入数组中,然后依次枚举它们时间。当你用完时,从头开始。
For a distribution by the percentages you gave do this:
Create a random number between 1 and 100 (inclusive)
As for the question of how to have a defined list, just put the destinations in order into an array and enumerate through them one at a time. When you run out, start again at the beginning.
另一种可能性是使用 for 循环填充一个大小为 100 的列表,并插入每个值乘以其权重。然后随机选择一个列表项。
例如,短列表(10 项)
List = {A,A,A,A,A,B,B,B,B,C}
在 0 到 9 之间随机。
Another possibility is to fill a list, with size 100, using a for-loop and inserting each value times its weight. Then randomly select a list-item.
Example, short list (10 items)
List = {A,A,A,A,A,B,B,B,B,C}
Random between 0 and 9.
这将创建一个 100 个字符长的随机列表,即 ABCDBCDCDD...
This will create a random list 100 characters long, ie ABCDBCDCDD...