增加随机化的重量

时间:2014-08-30 16:00:24

标签: javascript jquery

我很难找到任何有助于解决这个问题的资源:

假设我想生成一个介于1和5之间的随机数,但希望将随机化加权到底端(就像生成一对夫妇可能拥有的随机数的孩子一样,这更可能是1比5 )。我应该从哪里开始?这会涉及创建一个复杂的函数来映射该曲线,还是有一种方法可以帮助解决这个问题?

对于非常简单的集合,我想我可以创建一个数组,所以对于上面的例子我可以做,例如:

var children = [1,1,1,1,2,2,2,3,4,5];
return children[Math.floor(Math.random() * children.length)];

但这缺乏灵活性,并假设数据集是在脚本中手动创建的。

4 个答案:

答案 0 :(得分:5)

“儿童出生概率”具有高斯分布,这是二项分布的“连续极限”。如何使用binomial distribution

var val = Math.random()*5 + Math.random()*5;
// "val" will be between 0 and 10, but values around 5 are more probable
return 1 + Math.floor(Math.abs(val-5));

只需将其置于功能中并使“5”成为参数。

小测试(http://jsfiddle.net/yt6zvs8n/):

100个输出值:1,1,2,3,2,4,2,2,3,3,1,2,1,4,1,2,3,2,1,4,4 ,2,1,4,3,2,2,1,3,2,4,1,3,2,4,2,2,1,2,1,1,1,4,1,4,1 ,3,1,2,1,2,1,2,2,3,2,1,3,1,2,1,3,2,1,1,1,1,2,1,1,2 ,1,3,4,1,3,1,2,5,1,3,1,3,1,3,1,4,1,3,1,3,2,2,3,1,3 ,4,1,3

出现(直方图):38,28,21,12,1

答案 1 :(得分:3)

只要您使用整数,其中N是最大子值并且N不是那么大,您将需要O(n)空间和时间

我会回答假设你只使用从0N的整数,请参阅我的答案的 USAGE 部分,为什么你不需要指定它们当他们的体重为0时用手。

var weights = [0,4,3,1,1,1];

var number = weights.reduce(function (previous, current, index) {
    var value = Math.random() * (current|0);
    if (value > previous[0]) {
        return [value, index];
    }
    return previous;
}, [Math.random() * (weights[0]|0), 0])[0];

说明

使用索引作为整数,我们有:

  • 0,权重为0(永远不会出现)
  • 1,重量为4
  • 2,重量为3
  • 3,重量为1
  • 4,重量为1
  • 5,重量为1

用法

由于在范围方面思考起来并不容易,或者如果您不想在手动N之前指定所有值,您可以使用对象并通过指定键将其转换为数组{ {1}}等于length,就像这样

N + 1

答案 2 :(得分:1)

您可以使用为每个可能的结果分配任意权重的想法,而无需创建与此一样大的数组。足以为每个可能的选择分配任意权重,然后将随机数转换为适当的结果。随机滚动的可能结果甚至不需要是连续的整数范围。

例如:

var weights = { 1: 4, 2: 3, 3: 1, 4: 1, 5: 1 }

// pre-processing; modifies weights!
var runningTotal = 0;
for (var number in weights) {
    runningTotal += weights[number];
    weights[number] = runningTotal;
}

// generation
var seed = Math.floor(Math.random() * runningTotal);

// conversion of seed to result based on weights
for (var number in weights) {
    if (seed < weights[number]) {
        console.log("result: " + number);
        break;
    }
}

请注意,上述内容仅作为说明性示例,而不是编写此代码的最佳方式。

<强> See it in action

可以进一步概括这一点,以便您甚至不必提供明确指定每个可能结果的输入,但仍然适用相同的原则。

答案 3 :(得分:0)

由于数字Math.random()介于0和1之间,您所要做的就是创建一个数组,其中的答案是1,2,3,4或5,例如

var px = [
    { answer: 1, pxi: 0.0, pxf:0.40  },
    { answer: 2, pxi: 0.40, pxf:0.60  },
    { answer: 3, pxi: 0.60, pxf:0.80  },
    { answer: 4, pxi: 0.80, pxf:0.90  },
    { answer: 5, pxi: 0.90, pxf:1  }
]

我们可以说r是一个随机数字,所以如果r > pxi && r<=pxf它会返回x个答案。

所以,如果我足够清楚你可以看到这种方法重新提出1的可行性是40%,2是20%,3是20%,4是10%和5 10%,你可以很容易地改变概率通过改变范围pxi-pxf

来修改