【问题标题】:Javascript: Generate random numbers with fixed mean and standard deviationJavascript:生成具有固定均值和标准差的随机数
【发布时间】:2014-03-24 20:17:01
【问题描述】:

我的问题:

如何在 Javascript 中创建具有给定均值和标准差 (sd) 的随机数列表?

示例:

我想创建一个包含 5 个介于 1 到 10 之间的随机数的列表。结果平均值应该是 5,标准差应该是 2。

到目前为止我做了什么:

我的想法是(http://jsfiddle.net/QASDG/3/):

  1. 创建一个函数(名为“createData”),它创建 5 个介于 1 和 10 之间的随机数并将它们推入一个“数组”
  2. 此函数还应计算这 5 个数字的平均值(和标准差)。
  3. 使用“do-while”循环:只要“平均值变为 5”(并且“sd 变为 2”),就执行上述功能。但是当我调用 do-while 循环时,浏览器当然会崩溃,因为在很多情况下平均值为 != 5(而 sd != 2)。

注意:我还没有添加 SD,因为代码不是很优雅。

我从该站点找到了另一个脚本,该脚本声明:“此代码的目标是生成一个集合,其中包含 5 个正态分布的随机数,均值为 1.0,标准差为 0.5。” http://rosettacode.org/wiki/Random_numbers#JavaScript。我尝试通过添加“Math.floor”并更改“for”循环(i

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
}

我想如何修改我的代码:

我不太确定我是否理解了这段代码的数学部分。根据网页,它将创建一个正态分布(这很好但不是必需的)。所以我还需要的是:

  • 我在哪里可以更改给定的平均值和 sd(例如 mean = 5, sd = 2)以创建随机数(满足这些属性)。
  • 如何实现 1 到 10 之间的范围? (也许我可以使用类似:Math.floor(Math.random()*10)+1)

非常感谢!

【问题讨论】:

  • 不是Math.floor在那个地方总是四舍五入到0吗?
  • wikihow.com/Calculate-Standard-Deviation 现在编码。向我们展示您尝试了什么,然后我们提供帮助。我敢打赌这是你在学校的练习,老实说这很有趣,所以为了你自己的好不要寻找现成的解决方案,不要要求现成的解决方案
  • @Peter:请重新阅读问题。他不想计算标准差,他想生成一个具有所需属性的集合。此外,他确实提供了他尝试过的代码。
  • @Peter:那你为什么要评论“告诉我们你尝试了什么”并链接到wikihow.com/Calculate-Standard-Deviation
  • @OhDaeSu:在我看来,在 1 到 10 的范围内找不到 5 个整数,平均值 = 5,sd = 2。在你的情况下是否可以设置sd 不是数字,而是范围?

标签: javascript random numbers


【解决方案1】:

如何在 JavaScript 中创建具有给定均值和标准差 (sd) 的随机数列表?

这似乎是一个关于随机创建具有精确指定的mean 和精确指定的standard deviation 的数字列表的问题(而不是关于从具有给定均值和sd)。

一个简单的解决方案是绘制一个随机数列表,然后移动和缩放该列表以获得所需的均值和标准差,如 stats.stackexchange 中的described in this answer

假设,我们生成以下 5 个介于 1 和 10 之间的随机数:

4.527991433628388
6.3254986488276055
5.123502737960912
7.3331068522336125
9.069573681037484

此列表的平均值为 6.475934670737601,sd 为 1.8102412442104023

然后,我们像这样转换列表中的每个数字:

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

通过将 new mean 设置为 5 并将 new sd 设置为 2,我们得到以下转换后的列表:

2.847863379160965
4.83379450402964
3.505799227476338
5.947025358346529
7.865517530986525

计算这个列表的均值和标准差,确认它们确实是 5 和 2。

下面是用 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;
}

限制

请注意,由于浮点运算的精度限制,该演示有时会计算出精确的均值和 sd 以稍微偏离(例如 2.0000000000000004 的 sd 而不是 2)。另请注意,根据所需的均值和标准差,可能无法生成所需范围内的数字列表,如 math.stackexchange 上的this answer 中所述。这意味着转换后的列表可能与原始列表处于非常不同的范围内。另请注意,可能无法从给定范围内生成具有给定整数均值和整数 sd 的随机整数列表。

【讨论】:

  • 很好的答案,但代码真的伤了我的眼睛。我已经“现代化”了一点(见this jsFiddle)。
  • @BennyBottema,ES6 优势的一个很好的例子。我通常编写符合 ES3 的代码,除非我知道它会在哪里使用。对不起,如果这伤害了你的眼睛......
  • 别担心,这里有一个updated fiddle,它适用于 18 年前的 ES3 规范。我想如果它在 IE5 中工作就足够了,对吧?
  • 这是一个很好的答案,它彻底而充分地涵盖了该主题。并且看到它也是 only 一个,它应该得到赏金。感谢您响应这一行动呼吁!