【问题标题】:What are the chances of Math.random returning 0?Math.random 返回 0 的概率是多少?
【发布时间】:2019-02-04 22:58:48
【问题描述】:

就像this question 的提问者一样,我想知道为什么Math.ceil(Math.random() * 10) 不优于Math.floor(Math.random() * 10) + 1,并发现这是因为Math.random 有一个很小(但相关)的机会准确地返回0。但是有多小呢?

进一步的研究告诉我 this random number is accurate to 16 decimal places... well, sort of. 这是我很好奇的“某种”。

我了解浮点数的工作方式与小数不同。不过,我在细节上挣扎。如果这个数字是一个严格的十进制值,我相信机会是十分之一(或十亿,在美国系统中) - 1:1016

这是正确的,还是我搞砸了,或者浮点数有什么不同?

【问题讨论】:

  • 为什么从Math.random返回零对你很重要?
  • @TimBiegeleisen 正如我在问题中提到的,它对使用它生成随机整数有影响。我可以采用常见的做事方式(使用 .floor...+1 而不是 .ceil),但我想知道它是否实际上有必要防止不准确(或代码可能破坏台球迭代中的每一个)。此外,它可能会对这种方法的实际随机性产生影响。
  • 一个可能的 hackish 修复:检查是否完全等于零,如果为真,则添加 JavaScript 中可能的最小数字。我认为,这几乎对分布的影响可以忽略不计,但可以避免零问题。
  • @TimBiegeleisen 我的意思是,是的,但是添加 if (result == 0){result =+ Number.MIN_VALUE} 似乎比添加 .floor...+1 更笨拙。不过值得注意的是。
  • 有效数字

标签: javascript random floating-point


【解决方案1】:

JavaScript 是 ECMAScript 的一种方言。 ECMAScript-262 standard 无法准确指定 Math.random。相关条款说:

Math.random ( )

返回一个带正号的Number value,大于或等于+0?但严格小于1? ,使用implementation-defined 算法或策略随机或伪随机选择,在该范围内近似均匀分布。此函数不接受任何参数。

为不同的realms 创建的每个Math.random 函数必须从连续调用中产生不同的值序列。

在没有完整规范的情况下,无法就Math.random 返回零的概率做出明确的陈述。每个 ECMAScript 实现都可以选择不同的算法,并且不需要提供真正均匀的分布。

ECMAScript 使用 IEEE-754 基本 64 位二进制浮点格式作为其 Number 类型。在这种格式中,数字的有效位(小数部分)有 53 位。每个浮点数的形式为 sf • 2e,其中 s em>(符号)是+1或-1,f(小数)是有效数,是[0, 253中的整数,e(表示指数)是 [−1074, 971] 中的整数。如果设置了 f 的高位,则该数字被称为归一化(因此 f 在 [252, 253 ))。由于此答案中不考虑负数,因此对于此答案的其余部分,让 s 隐式 +1。

在 [0, 1) 中分配随机数的一个问题是可表示的值不是均匀分布的。 [½, 1) 中有 252 个可表示的值——所有在 [252, 253 中有 f 的值sup>) 和 e = -53。 [¼, ½) 中的值的数量相同——所有具有 f 的值在 [252, 253) 和 e = -54。由于在这个区间中有相同数量的数字,但区间是一半长,所以数字之间的间隔更近。类似地,在 [⅛, ¼) 中,间距再次减半。这一直持续到指数达到 -1074,此时正常数字以 f = 252 结束。小于此的数称为次正规数(或零),其中 f 在 [0, 252) 和 e = -1074 ,并且它们间隔均匀。

关于如何分配Math.random 的数字的一种选择是仅使用一组均匀间隔的数字f • 2−53 表示 f 在 [0, 253)。这使用 [½, 1) 中的所有可表示值,但仅使用 [¼, ½) 中的值的一半,[⅛, ¼) 中的值的四分之一,等等。这很简单,并且避免了分布中的一些奇怪之处。如果实施得当,产生零的概率是二分之一53

另一种选择是使用 [0, 1) 中的所有可表示值,每个值的概率与从它到下一个更高可表示值的距离成正比。因此,[½, 1) 中的每个可表示数字将以 1/253 的概率选择,[¼, ½) 中的每个可表示数字将以 1/254,[⅛, ¼) 中的每个可表示数字将以 1/255 的概率被选择,依此类推。此分布近似于实数上的均匀分布,并在浮点格式更精细的情况下提供更精细的精度。如果实施正确,产生零的概率是二分之一1074

另一种选择是使用 [0, 1) 中的所有可表示值,每个值的概率与段的长度成正比,其中可表示值是段中所有实数的最接近的可表示值。我将省略对该分布的一些细节的讨论,只是说它模仿了通过选择具有均匀分布的实数然后使用舍入到最近关系到偶数规则将其四舍五入到可表示值的结果.如果实施得当,产生零的概率是 21075 分之一。 (这种分布的一个问题是,在 [0, 1) 中的实数上的均匀分布有时会产生一个非常接近 1 的数字,以至于四舍五入会产生 1。这需要允许 Math.random 返回 1 或分布以某种方式被捏造,也许是通过返回下一个较低的可表示值而不是 1。)

我会注意到 ECMAScript 规范非常宽松,以至于有人可能会断言 Math.random 可以为每个可表示的值以相等的概率分配数字,而忽略它们之间的间距。这根本不会模拟真实数字的均匀分布,我预计很少有人会喜欢它。但是,如果实施,则返回的概率为零是 1021 • 252,因为有 252 个指数从 -53 到 -1074 的归一化数(1020 个值e),以及 252 个次正规数或零数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 2015-09-29
    • 2016-11-06
    • 2018-07-15
    • 2018-05-15
    • 2011-06-20
    相关资源
    最近更新 更多