【发布时间】:2011-11-14 17:14:16
【问题描述】:
为什么如果我使用随机数生成器和范围 0 - 9,我不会得到与将它与 floor 函数结合的相同的均匀分布?
【问题讨论】:
-
你能添加示例代码吗? (以及额外的功劳,一些比较两者并证明问题的统计数据)
标签: javascript
为什么如果我使用随机数生成器和范围 0 - 9,我不会得到与将它与 floor 函数结合的相同的均匀分布?
【问题讨论】:
标签: javascript
我真的很喜欢通过执行二进制“或 0”操作来触发 31 位 int 而不是 Math.floor()。从实际意义上讲,它使它稍微快一点(堆栈与堆)看起来更整洁,并且做同样的事情。这是一个获取数组随机元素的示例:
var ar=[1,2,3,4,5,6,7,8,9,0,'a','b','c','d']
console.log(ar[(Math.random() * ar.length) |0])
这似乎是过早的优化,但正如我所说,我喜欢它的外观,而且它比Math.floor() 需要更少的输入。使用Math.round() 需要额外的步骤(因为传播是1 到ar.length 而不是0 到ar.length-1)
【讨论】:
|0 将其强制为 int32 (四舍五入并键入),以便它可以放在堆栈中,而一般数字总是在堆中(以防它们最终变大或有小数点。)
Math.floor(Math.random() * 10) 给出了相当均匀的分布,而Math.round(Math.random() * 10) 则没有。
Math.floor() 为 [0, 1) 范围内的任何值返回 0(1 除外),为 [1, 2) 范围内的任何值返回 1,等等。
因此,如果我们在这些范围之一中获得数字的机会均等,我们将获得 0 和 1 的均等分布。
Math.round() 然而,对于低于 0.5 的值返回 0,对于低于 1.5 的值返回 1,等等。
所以我们实际上有一半的机会得到 0,因为只有 0 到 0.5 之间的值会四舍五入为 0。
╔═════════╦═════════╦═════════╗
║ Range ║ floor() ║ round() ║
╠═════════╬═════════╬═════════╣
║ [0, 1) ║ 0 ║ 0 or 1 ║
║ [1, 2) ║ 1 ║ 1 or 2 ║
║ [2, 3) ║ 2 ║ 2 or 3 ║
║ ... ║ ... ║ ... ║
║ [9, 10) ║ 9 ║ 9 or 10 ║
╚═════════╩═════════╩═════════╝
【讨论】:
Math.round(Math.random()) 在一种情况下是准确的,但是:当你“掷硬币”时,即想要 0 或 1。
Math.round(Math.random() * 10 + 1)?