Javascript: Generate random numbers with fixed mean and standard deviation

自作多情 提交于 2020-07-17 10:05:05

问题


My question:

How can I create a list of random numbers with a given mean and standard deviation (sd) in Javascript?

Example:

I want to create a list with 5 random numbers in a range between 1 to 10. The resulting mean should be 5 and the standard deviation should be 2.

What I've done so far:

My idea was (http://jsfiddle.net/QASDG/3/):

  1. Make a function (named "createData") which creates 5 random numbers between 1 and 10 and push them into an "array"
  2. This function should also calculate the mean (and the sd) of those 5 numbers.
  3. With a "do-while"-loop: Do the above function as long as the "average becomes 5" (and "sd becomes 2"). But when I call the do-while Loop, the browser crashes of course because there are a lot of cases when the average is != 5 (and the sd != 2).

Note: I haven't add the SD yet, since the code isn't very elegant.

I've found another script from this site which stated: "The goal of this code is to generate a collection filled with 5 normally distributed random numbers with a mean of 1.0 and a standard deviation of 0.5." http://rosettacode.org/wiki/Random_numbers#JavaScript. I've tried to adjust it according to my needs by adding "Math.floor" and changed the condition in the "for"-loop (i < 5).

function randomNormal() {
    return Math.floor(Math.cos(2 * Math.PI * Math.random()) * Math.sqrt(-2 * Math.log(Math.random())))
}

var a = []
for (var i=0; i < 5; i++){
    a[i] = randomNormal() / 2 + 1
}

How I want to modify my code:

I'm not quite sure whether I've understood the mathematical part of this code. According to the webpage it will create a normal distribution (which is great but not necessary). So what I need in addition is:

  • Where can I change the given mean and sd (e.g. mean = 5, sd = 2) in order to create random numbers (which fulfill those properties).
  • How do I implement the range between 1 and 10? (Maybe I could use something like: Math.floor(Math.random()*10)+1)

Thanks a lot!


回答1:


How can I create a list of random numbers with a given mean and standard deviation (sd) in JavaScript?

This appears to be a question about randomly creating a list of numbers that has an exactly specified mean and an exactly specified standard deviation (and not a question about drawing random numbers from a specific probability distribution with a given mean and sd).

A straightforward solution is to draw a list of random numbers, then to shift and scale this list to have the desired mean and sd, as described in this answer from stats.stackexchange.

Say, we generate the following 5 random numbers between 1 and 10:

4.527991433628388
6.3254986488276055
5.123502737960912
7.3331068522336125
9.069573681037484

This list has a mean of 6.475934670737601 and sd of 1.8102412442104023.

Then, we transform each number in the list like this:

newNum = oldSD * (oldNum - oldMean) / oldSD + newMean

By setting the new mean to 5 and new sd to 2, we get the following transformed list:

2.847863379160965
4.83379450402964
3.505799227476338
5.947025358346529
7.865517530986525

Computing the mean and sd of this list confirms that they are indeed 5 and 2.

Below is code demonstrating this approach in JavaScript:

// create a list of 5 random numbers between 1 and 10
var list = randomList(5, 1, 10);

// transform the list to have an exact mean of 5 and sd of 2
var newList = forceDescriptives(list, 5, 2);

// display the transformed list and descriptive statistics (mean and sd)
console.log('Transformed random list', newList, descriptives(newList));

// display the original list and descriptive statistics (mean and sd)
console.log('Original random list', list, descriptives(list));


/* demo functions */

function randomList(n, a, b) {
  // create a list of n numbers between a and b
  var list = [],
    i;
  for (i = 0; i < n; i++) {
    list[i] = Math.random() * (b - a) + a;
  }
  return list;
}

function descriptives(list) {
  // compute mean, sd and the interval range: [min, max]
  var mean,
    sd,
    i,
    len = list.length,
    sum,
    a = Infinity,
    b = -a;
  for (sum = i = 0; i < len; i++) {
    sum += list[i];
    a = Math.min(a, list[i]);
    b = Math.max(b, list[i]);
  }
  mean = sum / len;
  for (sum = i = 0; i < len; i++) {
    sum += (list[i] - mean) * (list[i] - mean);
  }
  sd = Math.sqrt(sum / (len - 1));
  return {
    mean: mean,
    sd: sd,
    range: [a, b]
  };
}

function forceDescriptives(list, mean, sd) {
  // transfom a list to have an exact mean and sd
  var oldDescriptives = descriptives(list),
    oldMean = oldDescriptives.mean,
    oldSD = oldDescriptives.sd,
    newList = [],
    len = list.length,
    i;
  for (i = 0; i < len; i++) {
    newList[i] = sd * (list[i] - oldMean) / oldSD + mean;
  }
  return newList;
}

Limitations

Note that, due to precision limits in floating-point arithmetic, the demo sometimes computes the exact mean and sd to deviate slightly (like an sd of 2.0000000000000004 instead of 2). Also note that, depending on the desired mean and sd, it may not be possible to generate a list of numbers within a desired range, as described in this answer on math.stackexchange. This means that the transformed list could be in a very different range than the original list. Also note that it is likely not possible to generate lists of random integers from a given range with a given integer mean and integer sd.



来源:https://stackoverflow.com/questions/22619719/javascript-generate-random-numbers-with-fixed-mean-and-standard-deviation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!