我试图设计一种(很好的)方法,从范围内的每一个数字都有一个权重的范围中选择一个随机数。简单地说:给定数字的范围(0,1,2),选择0有被选中的概率为80%的数字,1有10%的概率,2有10%的机会。
public function weightedRandom( Struct options ) {
var tempArr = [];
for( var o in arguments.options )
{
var weight = arguments.options[ o ] * 10;
for ( var i = 1; i<= weight; i++ )
{
arrayAppend( tempArr, o );
}
}
return tempArr[ randRange( 1, arrayLen( tempArr ) ) ];
}
// test it
opts = { 0=.8, 1=.1, 2=.1 };
for( x = 1; x<=10; x++ )
{
writeDump( weightedRandom( opts ) );
}
我正在寻找更好的解决方案,请提出改进或替代方案。
发布于 2018-08-07 10:57:36
这可能是可取的。
function weightedRand(spec) {
var i, j, table=[];
for (i in spec) {
// The constant 10 below should be computed based on the
// weights in the spec for a correct and optimal table size.
// E.g. the spec {0:0.999, 1:0.001} will break this impl.
for (j=0; j<spec[i]*10; j++) {
table.push(i);
}
}
return function() {
return table[Math.floor(Math.random() * table.length)];
}
}
var rand012 = weightedRand({0:0.8, 1:0.1, 2:0.1});
rand012(); // random in distribution...
另一种策略是在[0,1)
并迭代权重说明,如果随机数小于和,则返回相关值。当然,这假定权重之和为1。该解决方案没有预先的成本,但算法性能与规范中的条目数成线性关系。例如,在JavaScript中:
function weightedRand2(spec) {
var i, sum=0, r=Math.random();
for (i in spec) {
sum += spec[i];
if (r <= sum) return i;
}
}
weightedRand2({0:0.8, 1:0.1, 2:0.1}); // random in distribution...
发布于 2018-08-07 12:05:08
生成0到1之间的随机数R.
如果R在[0,0.1) - > 1
如果R在[0.1,0.2) - > 2
如果R在[0.2,1] - > 3中
如果无法直接获得介于0和1之间的数字,请生成一个范围内的数字,该范围将产生你想要的精度。例如,如果你有权重
(1,83.7%)和(2,16.3%),从1到1000滚动一个数字.1-837是1. 838-1000是2。
https://stackoverflow.com/questions/-100005922
复制相似问题