【问题标题】:Does Math.random() generate pseudorandom numbers uniformly?Math.random() 是否统一生成伪随机数?
【发布时间】:2017-07-02 20:10:33
【问题描述】:

this comment in another question 中,dimo414 指出 OP 代码的问题之一是它会不均匀地生成随机数。所以我想知道这是为什么?它是特定算法固有的吗?还是与Math.random() 本身有关?是因为[0.0, 1.0)区间内选择的数字的浮点表示吗?

附言我理解使用Random.nextInt() 的建议答案。我也想了解更多使用Math.random()的缺陷。

【问题讨论】:

  • Javadoc 说“... 返回值是伪随机选择的,并且(近似)均匀分布在该范围内。 ...”
  • 您能否重复原始问题中您认为相关的部分?现在,您只是要求对原始问题发表评论——即,如果原始问题消失,则很难将其视为一个单独的问题。
  • 这个详细讨论in this question。根本问题是Math.random() 返回的可能值与大多数离散范围不对应 1:1。通常,在尝试转换随机变量时很容易引入偏差或偏斜。最好留给专家。
  • 这两种方法之间的差异很小,在任何实际应用程序中绝对不值得担心。
  • @DawoodibnKareem 这也是我的评价。真正的问题是 OP 错误地从列表的大小中减去 1。

标签: java random


【解决方案1】:

它与Math.random() 几乎无关。 OP的帖子说了所有真正需要说的:

我的问题是,在几次不同的尝试中,最后一张卡片 洗好的牌组始终与最后一张牌是同一张牌 未洗牌。

换句话说,每次代码运行时,洗牌后的牌组至少有一张与未洗牌的牌组相同的牌。这肯定是确定性的,而不是随机的。

OP 算法的至少一个问题是每次迭代都会将随机数乘以比前一次迭代更小的数字。

更好的方法是创建 52 个随机数的列表。然后将卡片组中的每张卡片分配给列表中的每个元素。然后按随机数对列表进行排序,结果就是洗牌。

【讨论】:

  • 不,随机排序的效率低于使用 valid 洗牌算法,例如Fisher-Yates 或内置的Collections.shuffle
  • @pjs 也许是这样,但用例是一个 52 元素数组,并且 OP 更感兴趣的是了解根本不起作用的东西的缺陷。如果 OP 正在寻找可重用的最佳代码,那么 Collections.shuffle 可能是理想的选择。
  • “OP 算法的至少一个问题是每次迭代都会将随机数乘以比前一次迭代更小的数字。”这个“一个问题”几乎可以肯定是低效的,但并非不正确。我的意思是 OP 询问的错误是由实现中的算术错误引起的,而不是算法本身。
  • “换句话说,每次代码运行时,洗牌后的牌组与未洗牌的牌组至少有一张相同的牌。这肯定是确定性的,而不是随机的。”我相信这是因为实施中的错误。 OP 从大小中减去 1,因此,在最后一次迭代之前,永远不会选择原始列表的最后一个元素。
【解决方案2】:

Java 的Math.random()documented,用于返回“从[0, 1) 区间以(近似)均匀分布伪随机选择的数字。但是,尽管该文档指定它使用自己的 java.util.Random 实例,但没有记录它如何使用该实例生成随机数。例如,没有记录该方法是否会调用nextDouble 方法, 正是为java.util.Random 指定的。

【讨论】:

    猜你喜欢
    • 2019-07-27
    • 2011-07-02
    • 2015-08-07
    • 1970-01-01
    • 2016-11-08
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 2014-05-18
    相关资源
    最近更新 更多