【问题标题】:Math.random() returns value greater than one?Math.random() 返回大于一的值?
【发布时间】:2011-11-13 07:02:07
【问题描述】:

在玩 JavaScript 中的随机数时,我发现了一个令人惊讶的错误,大概是在 Google Chrome 的 V8 JavaScript 引擎中。考虑:

// Generate a random number [1,5].
var rand5 = function() {
  return parseInt(Math.random() * 5) + 1;
};

// Return a sample distribution over MAX times.
var testRand5 = function(dist, max) {
  if (!dist) { dist = {}; }
  if (!max) { max = 5000000; }
  for (var i=0; i<max; i++) {
    var r = rand5();
    dist[r] = (dist[r] || 0) + 1;
  }
  return dist;
};

现在,当我运行testRand5() 时,我得到以下结果(当然,每次运行都会略有不同,您可能需要将“max”设置为更高的值以显示错误):

var d = testRand5();
d = {
  1: 1002797,
  2: 998803,
  3: 999541,
  4: 1000851,
  5: 998007,
  10: 1 // XXX: Math.random() returned 4.5?!
}

有趣的是,我在 node.js 中看到了类似的结果,这让我相信它并非特定于 Chrome。有时会有不同或多个神秘值(7、9 等)。

谁能解释为什么我可能会得到我看到的结果?我猜这与使用parseInt(而不是Math.floor())有关,但我仍然不确定为什么会发生这种情况。

【问题讨论】:

    标签: javascript google-chrome random v8 parseint


    【解决方案1】:

    我建议将您的随机数函数更改为:

    var rand5 = function() {
      return(Math.floor(Math.random() * 5) + 1);
    };
    

    这将可靠地生成一个介于 1 和 5 之间的整数值。

    您可以在此处查看您的测试功能:http://jsfiddle.net/jfriend00/FCzjF/

    在这种情况下,parseInt 不是最佳选择,因为它会将您的浮点数转换为可以是多种不同格式(包括科学记数法)的字符串,然后尝试从中解析出一个整数。直接使用Math.floor() 对浮点数进行操作要好得多。

    【讨论】:

    • 他的函数如何最终生成像 7,9 和 10 这样的数字?
    • @Matt - 它可能与没有基数参数的 parseInt 有关,然后对转换为字符串的小数进行操作。所有这些都很糟糕。
    【解决方案2】:

    当然,这是一个parseInt() 陷阱。它首先将其参数转换为 string,这可以强制使用科学记数法,这将导致 parseInt 执行以下操作:

    var x = 0.000000004;
    (x).toString(); // => "4e-9"
    parseInt(x); // => 4
    

    我傻了……

    【讨论】:

    • 哇,不错的收获。我不知道 parseInt 先将数字转换为字符串。
    • 好吧,另一种选择是抛出TypeError,这是Java 方式。 javascript 中的大多数 API 只是尝试使用无效类型而不是抛出错误。
    【解决方案3】:

    当您碰巧生成一个非常小的数字时,就会出现极端情况,用指数表示,例如9.546056389808655e-8

    结合parseInt将参数解释为字符串,地狱就散了。正如我之前建议的那样,可以使用Math.floor 解决。

    用这段代码自己试试吧:

    var test = 9.546056389808655e-8;
    
    console.log(test); // prints 9.546056389808655e-8
    console.log(parseInt(test)); // prints 9 - oh noes!
    console.log(Math.floor(test)) // prints 0 - this is better
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-13
      • 1970-01-01
      • 1970-01-01
      • 2021-12-06
      相关资源
      最近更新 更多