如何在Javascript中生成偏斜的随机数?

4
使用Javascript,我该如何生成偏向于分布一端或另一端的随机数?或者理想情况下是范围内的某个点?
背景信息:我正在创建一个UI,其中使用了一个随机灰色方格网格。我使用Math.random()生成灰色的RGB值,但希望能够倾斜灰色,使其平均较暗或较亮,同时仍具有从黑到白的完整范围。
(我认为这类似于将Java随机数生成偏向于某个数字的问题,但我正在使用Javascript...)
非常感谢任何帮助。

2
你需要实现你想要的任何分布背后的数学。所有JavaScript运行时提供给你的都是均匀分布的伪随机数。 - Pointy
3个回答

12

Math.random()的结果乘以一个幂可以得到伽马曲线 - 这会改变0和1之间的分布,但是0和1仍然是端点。

var r= Math.pow(Math.random(), 2);
var colour= 'rgb('+r*255+', '+r*255+', '+r*255+')';

当 gamma 大于1时,输出会更暗;当 0 < gamma < 1 时,输出会更亮。(这里,“2”会给你一个二次曲线;对于平方根曲线来说,等距亮度为“0.5”。)


+1 还有其他可能的分布,但是考虑到问题描述中提到这些代表亮度值,伽马分布是一个不错的选择。 - John Watts
谢谢。这给了我我想要的视觉效果(稍微调整了一下)。代码也很简单易懂。 - edeverett

2
这个看起来有些粗糙,不如@bobince的回答优雅,但也无所谓。
//setup
var colours = [], num_colours = 10, skew_to = 255, skew_chance = 20;

//get as many RGB vals as required
for (var i=0; i<num_colours; i++) {

    //generate random grey
    var this_grey = Math.floor(Math.random() * 256);

    //skew it towards the @skew_to endpoint, or leave as-is?
    if (Math.floor(Math.random() * 100) >= skew_chance && this_grey != skew_to) {

            //skew by random amount (0 - difference between curr val and endpoint)
        var skew_amount = Math.floor(Math.random() * Math.abs(this_grey - skew_to));
        this_grey += ' (skewed to '+(skew_to < this_grey ? this_grey - skew_amount : this_grey + skew_amount)+')';
    }
    colours.push(this_grey);
}
console.log(colours);

基本上,它会生成随机灰度值,然后根据在“skew_chance”(作为百分比)中可能指定的偏斜概率决定是否进行偏斜。(如果您希望这是偶发而非恒定的)。如果决定进行偏斜,则从当前值向上或向下添加或减去一个随机数,具体取决于偏斜终点是在当前值之上还是之下。
该随机数是当前值与终点之间的绝对差异的0到N之间的数字。例如,如果当前值为40,而终点为100,则添加的数字将在0到60之间。
就像我所说的,@bobince的答案更为优雅!

1

这可能是一种略有不同的方法。

这种方法处理以下方式获取数字:

random = numberToSkewTo + random(-1,1)*stdDeviation

其中:

  • numberToSkewTo 是您想要偏斜的数字。
  • stdDeviation 是与 numberToSkewTo 的偏差。
  • numberToSkewTo + abs(stdDeviation) <= MAX_NUMBER
  • numberToSkewTo - abs(stdDeviation) >= MIN_NUMBER

以下代码的作用是,它选择一个随机数,其标准偏差不断增加,围绕给定数字生成。它返回结果的平均值。
function skew(skewTo,stdDev){
    var rand = (Math.random()*2 - 1) + (Math.random()*2 - 1) + (Math.random()*2 - 1);
    return skewTo + rand*stdDev;
}

function getRandom(skewTo){
    var difference = Math.min(skewTo-MIN_NUMBER, MAX_NUMBER-skewTo);
    var steps = 5;
    var total = 0.0;
    for(var i=1; i<=steps; i++)
        total += skew(skewTo, 1.0*i*difference/steps);
    return total/steps

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接