[removed] Generate random numbers with fixed mean and standard deviation

前端 未结 1 431
长情又很酷
长情又很酷 2021-02-13 20:01

My question:

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

Example:

1条回答
  •  梦毁少年i
    2021-02-13 20:35

    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 = newSD * (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.

    0 讨论(0)
提交回复
热议问题