是否有可能得到一个1-100之间的随机数,并将结果主要保持在40-60的范围内?我的意思是,它很少会超出这个范围,但我希望它主要在这个范围内……这是可能的JavaScript/jQuery?

现在我只使用基本的Math.random() * 100 + 1。


当前回答

当然这是可能的。随机抽取1-100。如果数字<30,则在1-100范围内生成数字,如果不在40-60范围内生成数字。

其他回答

最好的方法是生成一个随机数,该随机数平均分布在某一组数字中,然后对0到100之间的集合应用投影函数,其中投影更有可能击中你想要的数字。

通常,实现这一点的数学方法是绘制所需数字的概率函数。我们可以用钟形曲线,但为了计算方便,我们还是用翻转抛物线吧。

我们画一条抛物线,使它的根在0和100处,而不使它倾斜。得到如下方程:

f(x) = -(x-0)(x-100) = -x * (x-100) = -x^2 + 100x

现在,曲线下0到100之间的所有面积都代表了我们想要生成数字的第一个集合。在那里,生成是完全随机的。我们要做的就是求出第一个集合的上界。

下界当然是0。上限是函数在100处的积分,也就是

F(x) = -x^3/3 + 50x^2
F(100) = 500,000/3 = 166,666.66666 (let's just use 166,666, because rounding up would make the target out of bounds)

所以我们知道我们需要生成一个介于0到166666之间的数字。然后,我们只需要把这个数字投影到我们的第二个集合,它在0到100之间。

我们知道我们生成的随机数是输入x在0到100之间的抛物线的积分。这意味着我们只需假设随机数是F(x)的结果,然后解出x。

在这种情况下,F(x)是一个三次方程,形式为F(x) = ax^3 + bx^2 + cx + d = 0,下列表述成立:

a = -1/3
b = 50
c = 0
d = -1 * (your random number)

为x解出这个问题会得到你所寻找的实际随机数,它保证在[0,100]范围内,并且更接近中心而不是边缘。

这是3/4的加权解,40-60和1/4在这个范围之外。

function weighted() { var w = 4; // number 1 to w var r = Math.floor(Math.random() * w) + 1; if (r === 1) { // 1/w goes to outside 40-60 var n = Math.floor(Math.random() * 80) + 1; if (n >= 40 && n <= 60) n += 40; return n } // w-1/w goes to 40-60 range. return Math.floor(Math.random() * 21) + 40; } function test() { var counts = []; for (var i = 0; i < 2000; i++) { var n = weighted(); if (!counts[n]) counts[n] = 0; counts[n] ++; } var output = document.getElementById('output'); var o = ""; for (var i = 1; i <= 100; i++) { o += i + " - " + (counts[i] | 0) + "\n"; } output.innerHTML = o; } test(); <pre id="output"></pre>

好的,所以我决定添加另一个答案,因为我觉得我的最后一个答案,以及这里的大多数答案,使用某种半统计的方式来获得钟形曲线类型的结果回报。下面我提供的代码与掷骰子的工作方式相同。因此,得到1或99是最难的,但得到50是最容易的。

var loops = 10; //Number of numbers generated var min = 1, max = 50; var div = $("#results").html(random()); function random() { var values = ""; for (var i = 0; i < loops; i++) { var one = generate(); var two = generate(); var ans = one + two - 1; var num = values += ans + "<br/>"; } return values; } function generate() { return Math.floor((Math.random() * (max - min + 1)) + min); } <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div id="results"></div>

生成这样的随机数有很多不同的方法。一种方法是计算多个均匀随机数的和。你和多少个随机数以及它们的范围将决定最终分布的样子。

你加起来的数字越多,它就越向中心倾斜。在你的问题中已经提出了使用1个随机数的和,但正如你注意到的那样,它并不偏向于范围的中心。其他答案建议使用2个随机数的和或3个随机数的和。

通过取更多随机数的和,你可以得到更偏向范围中心的结果。在极端情况下,你可以取99个随机数字的和,每个数字都是0或1。这是一个二项分布。(二项分布在某种意义上可以被看作是正态分布的离散版本)。理论上,这仍然可以覆盖整个范围,但它有很大的偏向中心,你永远不会期望看到它到达端点。

这种方法意味着你可以调整你想要的偏差。

分布

 5% for [ 0,39]
90% for [40,59]
 5% for [60,99]

解决方案

var f = Math.random();
if (f < 0.05) return random(0,39);
else if (f < 0.95) return random(40,59);
else return random(60,99);

通用解决方案

random_choose([series(0,39),series(40,59),series(60,99)],[0.05,0.90,0.05]);

function random_choose (collections,probabilities)
{
    var acc = 0.00;
    var r1 = Math.random();
    var r2 = Math.random();

    for (var i = 0; i < probabilities.length; i++)
    {
      acc += probabilities[i];
      if (r1 < acc)
        return collections[i][Math.floor(r2*collections[i].length)];
    }

    return (-1);
}

function series(min,max)
{
    var i = min; var s = [];
    while (s[s.length-1] < max) s[s.length]=i++;
    return s;
}