我一直在寻找解决方案,但是我认为由于我的想法,我的搜索词组可能有点不完整,以支持不完全相关的主题。
我有一个数字,例如950,000。这表示整个系统中的[小部件]清单。我大约有200个“存储桶”,每个存储桶都应接收此清单的一部分,这样就不会剩下任何窗口小部件。
我想让每个存储桶收到不同的金额。我现在没有任何可靠的代码可以显示,但是这里有一些伪代码来说明我一直在想的事情:
//List<BucketObject> _buckets is a collection of "buckets", each of which has a "quantity" property for holding these numbers.
int _widgetCnt = 950000;
int _bucketCnt = _buckets.Count; //LINQ
//To start, each bucket receives (_widgetCnt / _bucketCnt) or 4750.
for (int _b = 0; b< _bucketCnt - 1; i++)
{
int _rndAmt = _rnd.Next(1, _buckets[i].Quantity/2); //Take SOME from this bucket...
int _rndBucket = _rnd.Next(0,_bucketCnt - 1); //Get a random bucket index from the List<BucketObject> collection.
_buckets.ElementAt(_rndBucket).Quantity += _rndAmt;
_buckets.ElementAt(i).Quantity -= _rndAmt;
}
这是处理该问题的统计学/数学上正确的方法,还是那里有处理该问题的分配公式?更重要的是,虽然此伪代码将运行200次(因此每个存储桶都有机会更改其数量),但根据小部件的类型(目前只有11种口味,但它必须运行X次)。预计将来会大大扩展。
{EDIT} 该系统用于商品交易游戏。 200家商店的数量必须有所不同,因为库存将决定该站点的价格。发行版甚至不可能,因为那样会使所有价格相同。随着时间的流逝,价格自然会失衡,但是库存必须开始失衡。而且所有库存的范围都必须至少相似(即,没有一家商店可以拥有一件商品,而另一家商店可以拥有900,000件商品)
答案 0 :(得分:0)
当然,有解决方案。您可以将Dirichlet Distribution用于此类任务。分布的属性是
Sum i x i = 1
因此,解决方案是从Dirichlet中抽取200个(等于存储桶数)随机值,然后将每个值乘以950,000(或任何总库存量),这将为您提供每个存储桶的项目数。如果您要进行非均匀采样,则可以调整Dirichlet采样中的alpha
。
每个存储桶中的项目应该四舍五入,但这很简单
如果您很难实现C#,我会在C#的某个地方进行Dirichlet采样-告诉我,我会进行挖掘
更新
我发现一些代码,.NET Core 2,摘录如下。我曾经用示例alpha
对Dirichlet RN进行采样,使它们全部不同是很简单的。
//
// Dirichlet sampling, using Gamma sampling from Math .NET
//
using MathNet.Numerics.Distributions;
using MathNet.Numerics.Random;
static void SampleDirichlet(double alpha, double[] rn)
{
if (rn == null)
throw new ArgumentException("SampleDirichlet:: Results placeholder is null");
if (alpha <= 0.0)
throw new ArgumentException($"SampleDirichlet:: alpha {alpha} is non-positive");
int n = rn.Length;
if (n == 0)
throw new ArgumentException("SampleDirichlet:: Results placeholder is of zero size");
var gamma = new Gamma(alpha, 1.0);
double sum = 0.0;
for(int k = 0; k != n; ++k) {
double v = gamma.Sample();
sum += v;
rn[k] = v;
}
if (sum <= 0.0)
throw new ApplicationException($"SampleDirichlet:: sum {sum} is non-positive");
// normalize
sum = 1.0 / sum;
for(int k = 0; k != n; ++k) {
rn[k] *= sum;
}
}