当前位置: 首页 > 知识库问答 >
问题:

java.util.Random.Nextint的实现

梁磊
2023-03-14
public int nextInt(int n) {
    if (n <= 0)
        throw new IllegalArgumentException("n must be positive");

    if ((n & -n) == n)  // i.e., n is a power of 2
        return (int)((n * (long)next(31)) >> 31);

    int bits, val;
    do {
        bits = next(31);
        val = bits % n;
    } while (bits - val + (n-1) < 0);
    return val;
}
  1. 它为什么特别对待n是2的幂的情况?只是为了表现吗?
  2. 它为什么拒绝位-val+(n-1)<0数字?

共有1个答案

弘浩瀚
2023-03-14

这样做是为了确保值在0n之间的均匀分布。您可能会想做一些类似的事情:

int x = rand.nextInt() % n;

但这将改变值的分布,除非n是2^31的除数,即2的幂。这是因为模运算符将产生大小不一样的等价类。

例如,让我们假设nextint()生成一个0到6之间的整数,您希望绘制0、1或2。容易,对吧?

int x = rand.nextInt() % 3;
0 % 3 = 0
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2
6 % 3 = 0

所以有3个值映射到0上,只有2个值映射到1和2上。您现在有一个偏差,因为0比1或2更有可能返回。

与往常一样,javadoc记录了这种行为:

在前面的描述中使用对冲“近似地”仅仅是因为下一个方法仅仅近似地是独立选择的比特的无偏置源。如果它是随机选择比特的完美源,那么所示的算法将以完美的一致性从所述范围中选择int值。

算法有点棘手。它拒绝会导致分布不均匀的值(因为2^31不能被n整除)。一个值被拒绝的概率取决于n。最坏情况为n=2^30+1,拒绝概率为1/2,循环终止前的预期迭代次数为2。

该算法特别处理n为二次方的情况:它从底层伪随机数生成器返回正确的高阶比特数。在没有特殊处理的情况下,将返回正确数量的低阶位。已知线性同余伪随机数发生器,如由该类实现的,在其低阶位的值序列中具有短周期。因此,如果n是2的小次方,这种特殊情况会大大增加连续调用该方法所返回的值序列的长度。

重点是我的。

 类似资料:
  • 本文向大家介绍android实现ViewPager的Indicator的实例代码,包括了android实现ViewPager的Indicator的实例代码的使用技巧和注意事项,需要的朋友参考一下 虽然在android5.0中design中有了TabLayout来实现ViewPager的Indicator,简单好用。但这个是我自己实现的,学习了很多,记录在这里。效果图: 第一步 新建一个类继承Lin

  • 本节是对前两节内容的实践。我们以“词嵌入(word2vec)”一节中的跳字模型和“近似训练”一节中的负采样为例,介绍在语料库上训练词嵌入模型的实现。我们还会介绍一些实现中的技巧,如二次采样(subsampling)。 首先导入实验所需的包或模块。 import collections import d2lzh as d2l import math from mxnet import auto

  • 一、前言 上一章我们讲解了Memcached的消息回应机制《Memcached源码分析 - Memcached源码分析之消息回应(3)》。从这一章开始我们慢慢讲解Memcached是如何存储数据的。 讲解本章前,我们先看一个Memcached存储数据的item的基本结构。 //item的具体结构 typedef struct _stritem {     //记录下一个item的地址,主要用于

  • 本文向大家介绍java 字符串的拼接的实现实例,包括了java 字符串的拼接的实现实例的使用技巧和注意事项,需要的朋友参考一下 java 字符串的拼接的实现实例 在实际的开发工作中,对字符串的处理是最常见的编程任务。本题目即是要求程序对用户输入的串进行处理。具体规则如下: 1. 把每个单词的首字母变为大写。 2. 把数字与字母之间用下划线字符(_)分开,使得更清晰 3. 把单词中间有多个空格的调整

  • 本文向大家介绍vue 实现的树形菜的实例代码,包括了vue 实现的树形菜的实例代码的使用技巧和注意事项,需要的朋友参考一下 下面一段代码给大家介绍vue 实现的树形菜单功能,具体代码如下所示: 总结 以上所述是小编给大家介绍的vue 实现的树形菜的实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对呐喊教程网站的支持!

  • 本文向大家介绍C++实现的链表类实例,包括了C++实现的链表类实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C++实现的链表类。分享给大家供大家参考。具体如下: 希望本文所述对大家的C++程序设计有所帮助。