- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
这是我不明白的code:
// Divide n by two until small enough for nextInt. On each
// iteration (at most 31 of them but usually much less),
什么?对于随机选择的
n
,我使用琐碎的
simulation进行
32
迭代,而
31
是平均值。
// randomly choose both whether to include high bit in result
// (offset) and whether to continue with the lower vs upper
// half (which makes a difference only if odd).
这很有道理。
long offset = 0;
while (n >= Integer.MAX_VALUE) {
int bits = next(2);
为这两个决定获取两位,这是有道理的。
long half = n >>> 1;
long nextn = ((bits & 2) == 0) ? half : n - half;
在这里,
n
是向上或向下四舍五入的
n/2.0
,很好。
if ((bits & 1) == 0) offset += n - nextn;
n = nextn;
我迷路了。
}
return offset + nextInt((int) n);
我可以看到它生成了一个适当大小的数字,但是它看起来相当复杂且相当慢,而且我绝对不明白为什么结果应该均匀分布。1
long
不能生成,但是显示它的实验可能要花费数年时间。
最佳答案
我认为您可能会误会...。让我尝试用我看待它的方式来描述算法:
首先,假设nextInt(big)
(nextInt,不是nextLong)能够正确生成0
(含)和big
(不含)之间的良好分布值。
此nextInt(int)
函数用作nextLong(long)
的一部分
因此,该算法通过循环工作直到该值小于Integer.MAX_INT为止,此时它使用nextInt(int)
。更有趣的是在那之前它做了什么...
在数学上,如果我们取一个数字的一半,则将其减去一半,然后再减去一半,再减去一半,依此类推,如此反复,那么它将趋于零。同样,如果取一个数字的一半,然后将其加到一半的一半,以此类推,那么它将趋向于原始数字。
该算法在这里所做的是只占用一半的数字。通过整数除法,如果数字为奇数,则有一个“大”一半和一个“小”一半。算法“随机地”选择那些一半(大或小)之一。
然后,它随机选择添加一半或不添加一半到输出。
它会将数字减半,并(可能)将一半相加,直到一半小于Integer.MAX_INT。那时,它只计算nextInt(half)
值并将其添加到结果中。
假设初始长限制远大于Integer.MAX_VALUE
,那么最终结果将获得nextInt(int)的所有好处,因为它具有一个较大的int值,该int值至少为状态的32位,对于所有较高位为2位的状态在Integer.MAX_VALUE
之上。
原始限制越大(距离Long.MAX_VALUE越近),循环迭代的次数就越多。在最坏的情况下,它将经历32次,但对于较小的限制,它将经历较少的时间。在最坏的情况下,对于很大的限制,您将获得用于循环的64位随机性,然后nextInt(half)
也需要任何随机性。
编辑:WalkThrough添加了-确定结果的数量比较困难,但是从0
到Long.MAX_VALUE - 1
的long的所有值都是可能的结果。使用nextLong(0x4000000000000000)
作为“证明”是一个很好的示例,因为所有减半过程将是偶数,并且它设置了63位。
因为设置了位63(因为位64会使数字为负,所以是最高有效位,这是非法的),这意味着我们将值减半32次,直到值<= Integer.MAX_VALUE(即0x000000007fffffff
-和half
)当我们到达那里时将是0x0000000004000000
。因为减半和移位是相同的过程,所以它认为要进行的减半与最高位集和第31位之间的差一样多。63-31为32,因此我们将减半32倍,因此我们将32减半在while循环中循环。 0x4000000000000000
的初始起始值意味着当我们将值减半时,一半将只设置一位,并且它将“沿行”该值-每次在循环中向右移1。
因为我仔细选择了初始值,所以很明显,在while循环中,逻辑本质上是在决定是否设置每个位。它采用输入值的一半(即0x2000000000000000),并决定是否将其添加到结果中。为了便于讨论,我们假设所有循环都决定将一半添加到偏移量,在这种情况下,我们从偏移量0x0000000000000000开始,然后每次循环都添加一半,这意味着每次添加:
0x2000000000000000
0x1000000000000000
0x0800000000000000
0x0400000000000000
.......
0x0000000100000000
0x0000000080000000
0x0000000040000000 (this is added because it is the last 'half' calculated)
0x3fffffffc0000000
(设置了从62到31的所有位)。
0x3fffffffffffffff
nextInt(0x40000000)
结果分布,我们就可以完美地覆盖
0x7fffffffc0000000
到
0x3fffffffffffffff
的值,而不会出现间隙。在while循环中具有完美随机性的情况下,我们的高位本应该是
0x0000000000000000
到
0x3fffffffc0000000
的完美分布结合起来,从0到我们的
0x4000000000000000
极限(不包括)都具有完全覆盖范围
nextInt(0x40000000)
的(假定的)最少31位状态,我们可以得到63位的状态(如果算上大/小半决定,则更多),并且具有完整的覆盖范围。
关于java - ThreadLocalRandom.nextLong(long n)如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19753088/
这里的任何人都可以帮助阐明“无法在 3 秒内从 SecureRandom 生成种子。没有足够的熵”警告消息从 ThreadLocalRandom 打印的条件吗? 我们能够在紧密循环中访问服务器时始终触
正在查看 Java 7 的新功能并发现添加了这个新类: For concurrent access, using ThreadLocalRandom instead of Math.random()
Instances of java.util.Random are threadsafe. However, the concurrent use of the same java.util.Rand
随机数生成是一个非常常见的操作,而且 Java 也提供了 java.util.Random 类用于生成随机数,而且呢,这个类也是线程安全的,就是有一点不好,在多线程下,它的性能不佳。 为什么多线程下
我试图验证 expected value formula在 java 。 我做了一些非常简单的事情,我模拟了掷骰子,但我将每一面映射到一个特定的值。所以每个值都有 1/6 的概率。 预期值确定为:23
是ThreadLocalRandom's nextInt() method (即没有任何参数的 nextInt() 方法)实际上生成一个没有范围的伪随机整数(即在 Integer.MIN_VALUE
当我在每个线程中创建新的 java.util.Random 对象或使用 ThreadLocalRandom.current().nextInt(3); 时有什么区别吗? ?根据我的阅读,应该使用 Th
我需要在多个线程中生成非重叠数字(随机或增量无关紧要,因为每个生成的数字都是唯一的)。我想我有两个选择 使用 AtomicInteger 并在所有线程之间共享 为每个线程使用具有不同开始和结束范围的
这个问题是关于 ThreadLocalRandom 在 OpenJDK 1.8.0 版本中的实现。 ThreadLocalRandom 提供了一个每线程随机数生成器,没有 Random 强加的同步开销
我正在阅读 Richard Warburton 写的一本 Java 8 书籍,并且有一个关于并行流的随机数生成的问题。这是他提供的两次掷骰子模拟示例: public Map parallelDiceR
我正在尝试导入 java.util.concurrent.ThreadLocalRandom 但我收到无法解析的错误消息“ThreadLocalRandom”。我检查了属性-> java 编译器下的编
我尝试打印只有 2 位小数的 double 组。但我在google上找不到怎么办。请帮忙吗? package com.company; import java.util.ArrayList; impo
我知道 Random 类会生成不安全的随机序列,在处理安全问题时我应该更喜欢使用 SecureRandom。但是 ThreadLocalRandom 呢?它更安全还是更不安全? // generate
ThreadLocalRandom类是在 jdk 1.7 中引入的。除了 java.util.Random 中已有的方法外,它还有一些方便的方法,例如 nextInt(least, bound) 和
我有一种方法可以获取最小值和最大值之间的随机 double 值。我的问题是,如果值是例如 0D 和 10D,我永远不会获得 10D 作为可能的结果,因为 nextDouble 第二个参数是独占的。 p
这是我不明白的code: // Divide n by two until small enough for nextInt. On each // iteration (at most 31 of
public static void shuffle(List list) { Random rnd = r; if (rnd == null) r = rnd = n
我正在试用 Java 7 的 ThreadLocalRandom并看到它在多个线程中生成完全相同的随机数。 这是我的代码,其中我创建了 5 个线程,每个线程打印出 5 个随机数: //5 thread
我希望跨多个线程使用(种子)Random 对象,javadoc 将我指向 ThreadLocalRandom这看起来很棒,只是我无法设置种子,所以我无法确保不同线程或运行之间的一致性。是否有任何使用
在我的应用程序中,我使用 ThreadLocalRandom() 生成种子,但它仅适用于 API 级别 21 +,我可以使用 Random code> 并得到相同的结果? 这是代码: public S
我是一名优秀的程序员,十分优秀!