【问题标题】:Random Number, Math.floor(...) vs Math.ceil(...)随机数,Math.floor(...) 与 Math.ceil(...)
【发布时间】:2013-03-27 16:12:44
【问题描述】:

我见过很多生成随机数的代码

// random integers in the interval [1, 10]
Math.floor(Math.random()*10 + 1)

无论如何,我觉得我错过了一些东西。为什么人们不使用更简洁的方式

Math.ceil(Math.random()*10);

?

我尝试测试随机性,到目前为止似乎是正确的。

其实后面的代码

// will generate random integers from 1 to 4
var frequencies = [ 0, 0, 0, 0, 0 ]; // not using the first place
var randomNumber;
for ( var i = 0; i < 1*1000*1000; ++i ) {
   randomNumber = Math.ceil(Math.random()*4);
   frequencies[randomNumber]++;
}

for ( var i = 1; i <= 4; ++i ) {
   console.log(i +": "+ frequencies[i]);
}

打印出来

1: 250103
2: 250161
3: 250163
4: 249573

我错过了什么?

快速 OT:有没有更简洁的方式来声明和初始化频率?我的意思是像 C++ 中的 frequencies[5] = { 0 };...

【问题讨论】:

  • Math.ceil(Math.random()*10);生成[0,10],虽然0的概率非常非常小...
  • 另外,10的概率小于1~9,因为Math.random()从不返回1。
  • 关于您的 OT 问题:并非如此。 JavaScript 没有数组初始化。 JavaScript 数组(基本上)只不过是具有数字键名和长度属性的对象。你能得到的最接近的是new Array(size),但它不会初始化为0,而是初始化为undefined
  • 同样有趣的是,Math.ceil 比 Math.floor 慢 90%:jsperf.com/convert-to-integer

标签: javascript random


【解决方案1】:

MDN reference 中所述,关于Math.random()

返回 [0, 1) 范围内的浮点伪随机数,即从 0(包括)到但不包括 1(不包括),然后您可以将其缩放到所需的范围。

既然 Math.random 可以返回 0,那么 Math.ceil(Math.random()*10) 也可以返回 0,并且该值超出了您的 [1..10] 范围。


关于你的第二个问题,见Most efficient way to create a zero filled JavaScript array?

【讨论】:

  • 我现在真的很好奇是否真的有可能得到 0,如果是的话,实际几率是多少!我尝试了几次,编辑了问题的脚本,not 不包括零,并生成了十亿个随机整数,运行大约需要 7 秒,frequencies[0] 总是返回零。
  • 等等,如果Math.random() returns 16 decimal places of accuracy 我想它会是……十亿分之一?类似的东西?
  • @IsaacReefman 你知道墨菲定律吗? :D。无论如何,概率几乎为零但不是零。
  • @FabrizioCalderan 可以证实墨菲定律。我刚刚有一个 node.js 包在向我的团队演示一个不相关的新功能时,已经可靠运行了几个月,但出现了一个前所未有的错误,因为 Math.random() 选择了 那个 时刻第一次返回0。经验教训:如果在功能中使用 Math.random(),请对其进行测试,针对一组不同值代替随机值运行它,并在该数组中包含 0
【解决方案2】:

这里首选Math.floor(),因为Math.random()的范围。

例如,Math.random() * 10 给出了[0, 10) 的范围。使用Math.floor(),您将永远得到10的值,而Math.ceil() 可能给出0

【讨论】:

    【解决方案3】:

    区间[1, 10]中的随机整数:

    Math.floor(Math.random()*10 + 1)
    

    区间 [0, 10] 中的随机整数:

    Math.ceil(Math.random()*10);
    

    这取决于你需要什么。

    【讨论】:

    • 在使用 ceil() 时获取 [0,10] 范围内的随机数将是一种非常糟糕的方法,因为实际上零会被饿死。
    • 是的,完全正确...但是如果有一天系统的某些部分由于非常罕见的情况而崩溃,那将是一种耻辱。
    • 几乎从不采用 0 的事实并非罕见。
    • 不确定你的意思。但是,如果您指望 0 不会被 random() 调用返回,那么有一天您可能会感到不快。这就是我要说的。此外,这个答案的重点是说明两者之间的区别 - 他暗示它们是相同的......
    • 你应该删除这个答案。 Math.ceil() 从不在您想要生成随机整数时使用正确的函数。始终使用Math.floor(),如果下限不为零,则添加下限。以 Math.ceil(Math.random()*10) 的第二个示例作为尝试获取 0 到 10 的数字,正确的方法是 Math.floor(Math.random()*11)
    猜你喜欢
    • 1970-01-01
    • 2014-05-07
    • 2017-09-02
    • 1970-01-01
    • 2022-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多