代码之家  ›  专栏  ›  技术社区  ›  ant

在java中生成随机整数

  •  1
  • ant  · 技术社区  · 14 年前

    如何生成随机整数,但确保它们永远不会重复?

    Random randomGenerator = new Random();
    randomGenerator.nextInt(100);
    
    EDIT I
    

    我在寻找最有效的方法,或者最不坏的方法

    EDIT II
    

    范围并不重要

    10 回复  |  直到 14 年前
        1
  •  15
  •   Tom Hawtin - tackline    14 年前
    ArrayList<Integer> list = new ArrayList<Integer>(100);
    for(int i = 0; i < 100; i++)
    {
      list.add(i);
    }
    Collections.shuffle(list);
    

    现在, list 包含从0到99的数字,但顺序是随机的。

        2
  •  7
  •   Jherico    14 年前

    如果你想要的是一个伪随机的不重复的数字序列,那么你应该看看 linear feedback shift register

    您可以找到java实现 here

        3
  •  4
  •   Stephen C    14 年前

    如何生成随机整数,但确保它们永远不会重复?

    根据定义 .

    置换 一定范围内的数字;例如 0 99 . 即使这样,一旦你使用了这个范围内的所有数字,重复也是不可避免的。

    记得 所有以前生成的数字。对于大型 N 那需要很多记忆。

    记住大量数字的另一种方法是使用长周期的伪随机数生成器,并返回 整个州

    (这个答案可能远远超出了OP的兴趣。。。但有人可能会发现它很有用。)

        4
  •  2
  •   David Underhill    14 年前

        5
  •  1
  •   Gian    14 年前

    根据应用程序的不同,您还可以生成一个严格递增的序列,即从一个种子开始,向其添加一个范围内的随机数,然后将该结果作为下一个数字的种子重新使用。您可以通过调整范围来设置它的可猜测性,将其与您需要的数字数量进行平衡(例如,如果您进行了高达1000的增量步进,您就不会很快耗尽64位无符号整数)。

    也就是说,这个解决方案不容易出现定时攻击,其他一些解决方案就是这样建议的。

        6
  •  1
  •   Brendan Long    14 年前

    Matthew Flaschen提出了一种适用于小数字的解决方案。如果你的范围真的很大,最好是用某种方法来跟踪使用过的数字 Set

    Set usedNumbers = new HashSet();
    Random randomGenerator = new Random();
    int currentNumber;
    while(IStillWantMoreNumbers) {
        do {
            currentNumber = randomGenerator.nextInt(100000);
        } while (usedNumbers.contains(currentNumber));
    }
    

    不过,您必须小心,因为随着“已用”数字的比例增加,此函数所用的时间将呈指数增长。如果你的范围比你需要生成的数字要大得多,这才是个好主意。

        7
  •  1
  •   Matunos    12 年前

    由于没有足够的声誉,我不能对前面的答案发表评论(这似乎是倒退。。。难道我不能评论别人的答案,却不能提供自己的答案吗?。。。无论如何,我想提到的是,依赖Collections.shuffle()存在一个主要缺陷,它与集合的内存限制关系不大:

    shuffle()使用随机对象,在Java中使用48位种子。这意味着有281474976710656个可能的种子值。好像很多。但是如果你想用这个方法洗牌52张牌。52张牌组有52张(超过8*10^67种可能的配置)。由于如果使用相同的种子,总是会得到相同的洗牌结果,因此可以看到Collections.shuffle()可以生成的52张牌组的可能配置只是所有可能配置的一小部分。

    事实上,Collections.shuffle()不是一个很好的解决方案,它不适合对超过16个元素的任何集合进行洗牌。一个17元素的集合有17个元素!或355687428096000配置,这意味着74212451385344配置永远不会是17元素列表的Collections.shuffle()的结果。

    根据您的需要,这可能是非常重要的。洗牌/随机化技术选择不当会使软件易受攻击。例如,如果您使用Collections.shuffle()或类似的算法来实现一个商业扑克服务器,您的洗牌将是有偏见的,一个精明的计算机辅助玩家可以利用这些知识为他们带来好处,因为这会降低胜算。

        8
  •  1
  •   Hot Licks    12 年前

    byte randomSeed = rng.nextInt(255);
    for (int i = 0; i < 256; i++) {
        byte randomResult = randomSeed ^ (byte) i;
        << Do something with randomResult >>
    }
    

    适用于2的任意幂。

        9
  •  0
  •   Tim Bender    14 年前

    如果值的范围不是有限的,那么可以创建一个对象,该对象使用列表来跟踪所用整数的范围。每次需要一个新的随机整数时,都会生成一个,并根据使用的范围进行检查。如果整数未使用,则它会将该整数添加为新的已使用范围,将其添加到现有的已使用范围,或者根据需要合并两个范围。

        10
  •  0
  •   wannik    13 年前