【问题标题】:What is the minimal non-zero value Math.random() can return in javascriptMath.random() 可以在 javascript 中返回的最小非零值是多少
【发布时间】:2015-04-30 11:21:37
【问题描述】:

我知道计算机不能使用连续体。 Math.random() javascript 函数返回一个介于 0(包括)和 1(不包括)之间的浮点数。我想知道它可以返回的最小非零数是多少。什么“步骤”有这个功能?

【问题讨论】:

  • 我相信在大多数实现中,粒度是2^53。所以答案是 2^-53。
  • The specusing an implementation-dependent algorithm or strategy,我猜最小的结果是1 / Number.MAX_VALUE 给你的(假设非零结果,例如5.562684646268003e-309
  • 浮点值让它变得有趣。对于一个典型的 C 实现,它返回一个 integerRAND_MAX 可能低至 65535。当然这会导致很多小数,最终粒度是 1/65536,即大约 4 位小数。

标签: javascript random


【解决方案1】:

标准肯定没有表达这个值,所以它取决于实现(在这一点上有点夸大其词,可能即使是因为Math.random() 的结果返回 0.42 的实现仍然符合规范)。

IEEE754格式的64位归一化浮点数可以表示的最小正数是2-1022,即2.2250738585072014 × 10-308

但是,浮点表示使用不同的分辨率,具体取决于大小。

对于接近 1 的数字,分辨率为 2-53。可能(只是可能)许多实现选择一个介于 0 和 253-1 之间的随机整数 n 并用作结果 n/9007199254740992

【讨论】:

  • 那数看起来像这样在十进制:0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072014。它很小。
  • 令我惊讶的是,如果您将该十进制字符串传递给一个字符串以进行浮点转换,结果是正确的(即使它当然是他们使用的测试用例之一)。
【解决方案2】:

几乎可以肯定,这不仅仅是随机选择任何浮点数。

这不能准确地表示随机函数的步长,因为它甚至不会接近均匀分布。假设您得到了 2-1022 “步长”(适合浮点数的最小非零值),再加上 0.25 作为随机值。好吧,这将四舍五入为 0.25,因为浮点数不能代表该精度。因此,由于四舍五入,您拥有全部等于 0.25 的“值”。这甚至都不是统一的。

我会说更可能生成一个浮点数,指数设置为 0,尾数为随机位,这将导致步骤 2-51(我认为 XD)之间的随机性1(包括)和 2(不包括),然后您可以从中减去 1。在这种情况下,步长将是尾数的大小。

【讨论】:

  • 您不同意哪一部分?我所说的标准没有涵盖这一点,或者我在说明双精度数可以表示的最小数字是多少?
  • @6502 两部分都是正确的,但第二部分在这种情况下并不真正相关并且有点误导,因为它有点暗示你声称这是随机函数的步骤。至少,我是这么解释的 XD
  • 无论如何都要点。编辑了(可能)实现可以做什么来提取统一随机数的答案。
  • "选择随机位" ...浮点存储格式肯定会影响结果吗? (必须找到参考。我知道这会导致对数传播,而不是线性传播。)
  • @Jongware:您可以通过固定指数并随机选择 52 个尾数位来获得均匀分布。稍后您可以对表示进行规范化。
【解决方案3】:

ECMA provides no guidelines for the precision of randomness

返回一个带正号的数值,大于或等于 0 但小于 1,随机或伪随机选择,在该范围内近似均匀分布,使用依赖于实现的算法或策略。此函数不接受任何参数。

Math.random() 返回一个介于 0 和 1 之间的 double。我们可以忽略指数和符号,剩下 53 个可用位。这意味着完美世界中数字之间的最小步长是1/2^53 == 0.00000000000000011102230246251565404236316680908203125

然而,流行的 JavaScript 实现提供了不同级别的随机性:

  • V8(Chrome、Chromium、node.js):32 位 (src)
  • JavaScriptCore (Safari) 32 位 (src)
  • SpiderMonkey (Firefox):53 位 (src)
  • Internet Explorer 53 位

虽然有些环境会给你更多,但最不常见的标准是 32 位。即使在服务器上,您的 node.js 应用程序也只能获得 32 位。

如果您希望您的应用程序在任何地方都能正确运行,您可以依赖的最低精度是 1/2^32 == 0.00000000023283064365386962890625

【讨论】:

  • 我坚信假设每个用户都使用一个实现是懒惰的,通常是不好的建议。不管你喜不喜欢,其他浏览器被使用,应该被考虑在内。
【解决方案4】:

我不知道规范是怎么说的,但是在 Chrome、Firefox 和 IE11 的控制台中进行的快速测试表明精度永远不会超过小数点后 20 位。

自己测试一下:

for (var i = 0; i < 1000; ++i) console.log(Math.random());

或者在大量迭代后看到最小的数:

var smallest = 1;
for (var i = 0; i < 1000000; ++i) smallest = Math.min(smallest, Math.random());

【讨论】:

  • 我对javascript不是很熟悉,但是console.log默认只写20位小数的几率是多少?
  • 这种测试是确定最小值的非常糟糕的方法。在 1.0 和 10^(-20) 之间有难以想象的大量数字,因此random() 选择小于 10^(-20) 的数字的机会几乎为零 - 无论您为循环选择多少次迭代。因此,即使您可能永远不会看到 random() 生成小于 10^(-20) 的数字,因为它非常不可能。
  • 从纯数学的角度来看,您至少需要 10^20 次迭代才能获得小于 10^(-20) 的值。如果我们暂时忘记了做这样的事情是多么低效,你仍然永远无法确定你的答案是正确的。因为无论您运行了多少次迭代,总有可能您只是运气不好,并且仍然没有返回可能的最低数字。所以回到我原来的陈述,确定这样的事情真的很糟糕。
  • @MooingDuck:控制台使用 E 表示法输出全精度,因此这不是限制因素。
  • @XaverKapeller:我并不是说你可以用我的方法得到最小的数字。我说你可以“在大量迭代之后”得到最小的数字。我的观点是,一组 1,000,000 中的每个数字都落在小数点后 20 位精度的几位数字内,因此这可能是您对 Math.random() 的调用所期望的范围。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-04
  • 1970-01-01
  • 2021-11-11
  • 2021-12-27
  • 1970-01-01
  • 2014-07-15
  • 2013-10-17
相关资源
最近更新 更多