也就是说,它将永远不会连续生成超过16个偶数,并带有一些特定upperBound参数:
Random random = new Random();
int c = 0;
int max = 17;
int upperBound = 18;
while (c <= max) {
int nextInt = random.nextInt(upperBound);
boolean even = nextInt % 2 == 0;
if (even) {
c++;
} else {
c = 0;
}
}
Run Code Online (Sandbox Code Playgroud)
在这个例子中,代码将永远循环,而当upperBound例如是16时,它会很快终止.
这种行为的原因是什么?方法的javadoc中有一些注释,但我没理解它们.
UPD1:代码似乎以奇数上限终止,但可能会遇到偶数
UPD2:我修改了代码以捕获c评论中建议的统计信息:
Random random = new Random();
int c = 0;
long trials = 1 << 58;
int max = 20;
int[] stat = new int[max + 1];
while (trials > 0) {
while (c <= max && trials > 0) {
int nextInt = random.nextInt(18);
boolean even = nextInt % 2 == 0;
if (even) {
c++;
} else {
stat[c] = stat[c] + 1;
c = 0;
}
trials--;
}
}
System.out.println(Arrays.toString(stat));
Run Code Online (Sandbox Code Playgroud)
现在它试图20在行中达到平衡 - 以获得更好的统计数据,而且upperBound仍然存在18.
事实证明结果令人惊讶:
[16776448, 8386560, 4195328, 2104576, 1044736,
518144, 264704, 132096, 68864, 29952, 15104,
12032, 1792, 3072, 256, 512, 0, 256, 0, 0]
Run Code Online (Sandbox Code Playgroud)
首先它按预期减少2倍,但请注意最后一行!在这里它变得疯狂,捕获的统计数据似乎是完全奇怪的.
这是一个对数比例的条形图:

如何c获得17256倍的价值又是另一个谜
http://docs.oracle.com/javase/6/docs/api/java/util/Random.html:
该类的实例用于生成伪随机数流.该类使用48位种子,使用线性同余公式进行修改.(参见Donald Knuth,计算机程序设计的艺术,第3卷,第3.2.1节.)
如果使用相同的种子创建两个Random实例,并且对每个实例都进行相同的方法调用序列,则它们将生成并返回相同的数字序列.[...]
它是伪随机数生成器.这意味着您实际上并没有掷骰子,而是使用公式根据当前随机值计算下一个"随机"值.为了创造随机化的假象,seed使用了a .种子是公式中用于生成随机值的第一个值.
显然javas随机实现("公式"),连续生成不超过16个偶数.
这种行为是seed通常用时间初始化的原因.根据您何时启动程序,您将获得不同的结果.
这种方法的好处是可以产生可重复的结果.如果你有一个游戏生成"随机"地图,你可以记住种子,如果你想再次播放它,重新生成相同的地图.
对于真随机数,某些操作系统提供了特殊设备,可以从外部事件(如鼠标移动或网络流量)中生成"随机性".但是我不知道如何利用java进入那些.
从用于secureRandom的Java doc :
许多SecureRandom实现采用伪随机数生成器(PRNG)的形式,这意味着它们使用确定性算法从真正的随机种子生成伪随机序列.其他实现可以产生真正的随机数,而其他实现可以使用两种技术的组合.
需要注意的是SecureRandom的确实不保证真正的随机数,无论是.
假设随机数只有0-7的范围.现在我们使用以下公式生成下一个"随机"数字:
next = (current + 3) % 8
Run Code Online (Sandbox Code Playgroud)
顺序变成了0 3 6 1 4 7 2 5.
如果你现在拿种子3你所做的就是改变起点.
在这个仅使用前一个值的简单实现中,每个值只能在序列换行并再次启动之前出现一次.否则会有一个无法到达的部分.
想象一下序列0 3 6 1 3 4 7 2 5.这些数字0,4,7,2 and 5永远不会产生多次(因为它们可能永远不会产生种子),因为一旦序列循环3,6,1,3,6,1,....
可以将简化的伪随机数生成器视为范围内所有数字的排列,并使用种子作为起点.如果它们更高级,则必须使用可能多次出现相同数字的列表替换排列.
更复杂的发生器可以具有内部状态,允许在序列中多次出现相同的数字,因为状态允许发生器知道继续的位置.
| 归档时间: |
|
| 查看次数: |
2074 次 |
| 最近记录: |