最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

math - How to generate skewed random numbers in Javascript? - Stack Overflow

programmeradmin5浏览0评论

Using Javascript, how can I generate random numbers that are skewed towards one end or the other of the distribution? Or ideally an point within the range?

For context: I'm creating a UI that has uses a grid of random grey squares. I'm generating the grey's RGB values using Math.random() but would like to be able to skew the greys to be on average darker or lighter while still having the full range from black to white represented.

(I think this is a similar question to Skewing java random number generation toward a certain number but I'm working with Javascript...)

Any help greatly appreciated.

Using Javascript, how can I generate random numbers that are skewed towards one end or the other of the distribution? Or ideally an point within the range?

For context: I'm creating a UI that has uses a grid of random grey squares. I'm generating the grey's RGB values using Math.random() but would like to be able to skew the greys to be on average darker or lighter while still having the full range from black to white represented.

(I think this is a similar question to Skewing java random number generation toward a certain number but I'm working with Javascript...)

Any help greatly appreciated.

Share Improve this question edited May 23, 2017 at 12:02 CommunityBot 11 silver badge asked Jul 8, 2012 at 12:42 edeverettedeverett 8,2181 gold badge34 silver badges28 bronze badges 1
  • 2 You'll have to implement the maths behind whatever distribution you want. All JavaScript's runtime will give you are uniformly-distributed pseudo-random numbers. – Pointy Commented Jul 8, 2012 at 12:44
Add a ment  | 

3 Answers 3

Reset to default 13

Raise Math.random() to a power to get a gamma curve - this changes the distribution between 0 and 1, but 0 and 1 stay constant endpoints.

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

For gamma>1, you will get darker output; for 0<gamma<1 you get lighter. (Here, '2' gives you the x-squared curve; the equidistant lightness would be '0.5' for the square-root curve.)

This seems a little crude and less graceful than @bobince's answer, but what the hell.

//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);

Essentially it generates random greys then decides, based on probably specified (as a percentage) in skew_chance, whether to skew it or not. (In case you wanted to make this occasional, not constant). If it decides to skew, a random number is then added or subtracted from the grey value (depending on whether the skew endpoint is under or above the current value).

This random number is a number between 0 and the absolute difference between the current value and the endpoint, e.g. if current value is 40, and the endpoint is 100, the number added would be between 0 and 60.

Like I say, @bobince's answer is somewhat, er, more graceful!

[This might be a little different approach.]

This approach deals with getting the number in the following fashion:

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

Where:

  • numberToSkewTo is the number you want to skew towards.
  • stdDeviation is the deviation from numberToSkewTo
  • numberToSkewTo + abs(stdDeviation) <= MAX_NUMBER and
  • numberToSkewTo - abs(stdDeviation) >= MIN_NUMBER

What the following code does is, it pick a random number around the given number with constantly increasing standard deviations. It returns the average of results.

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

}
发布评论

评论列表(0)

  1. 暂无评论