【问题标题】:Generating Unique Set of Random Integers生成唯一的随机整数集
【发布时间】:2012-02-15 15:19:25
【问题描述】:

这是我第一次构建应用程序,但遇到了问题。我正在制作这个应用程序,它只会生成随机数,有时它会向我显示两次随机数。这不是我的目标,那么如何对其进行编程以显示随机数而不重复?

这是我的代码:

    package rando.mizer;

    import java.util.Random;

    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;

    public class RandomizerFinalActivity extends Activity {
        /** Called when the activity is first created. */   
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            Button buttonGenerate = (Button)findViewById(R.id.button1);
            final EditText aantalT= (EditText)findViewById(R.id.editText1);
            final EditText laagsteT = (EditText)findViewById(R.id.editText2);
            final EditText hoogsteT = (EditText)findViewById(R.id.editText3);
            final EditText uitvoerT = (EditText)findViewById(R.id.editText4); 



            buttonGenerate.setOnClickListener(new Button.OnClickListener(){

               public void onClick(View arg0) {
                    final int aantal = Integer.parseInt(aantalT.getText().toString());
                    final int laagste = Integer.parseInt(laagsteT.getText().toString());
                    final int hoogste = Integer.parseInt(hoogsteT.getText().toString());

                    uitvoerT.setText("");
                    Random r = new Random();

                    int aNumber;
                    String build = "";


                for(int i = 0; i < aantal; i++) {
                    aNumber = laagste + r.nextInt(hoogste + 1 - laagste);
                    build += aNumber + ",\n";
                }

                    uitvoerT.setText(build);


              }

            });
        }
    }

【问题讨论】:

  • random 是随机的,它可能会多次生成相同的数字。您可以在循环中生成数字,将它们分配给一个集合,这将保证您不会有重复。
  • 我们在谈论多少个数字?
  • 没有确切的随机数数量。使用该应用程序的人可以在 anantalT 中说出他或她想要多少个随机数。我试过这个: ArrayList dubbel=new ArrayList(); for(int i = 0; i
  • ARRG 和我的解决方案可以满足您的需求。

标签: java random duplicates


【解决方案1】:

使用 Collections.shuffle 是个好主意,但您不需要随机播放所有数字。使用起来会更有效率:

// return nNumbers distinct values from low to (high - 1)
public List<Integer> getRandoms(int low, int high, int nNumbers) {
    int range = high - low;
    List<Integer> workArray = new ArrayList(range);
    for (Integer i = low; i < high; i++)
        workArray.add(i);

    // Put the chosen values at the start of the array one by one 
    // (and then do not touch the start of the array).
    int pseudoStartIndex = 0;
    while (pseudoStartIndex < nNumbers) {
        int randomIndex = pseudoStartIndex + 
                          random.nextInt(range - pseudoStartIndex); 
        Integer tempSwap = workArray.get(pseudoStartIndex);
        workArray.set(pseudoStartIndex, workArray.get(randomIndex));
        workArray.set(randomIndex, tempSwap);
        pseudoStartIndex++;
    }
    return workArray.subList(0, nNumbers);
}

它基本上是Fisher-Yates shuffle,但只应用于少数元素。

【讨论】:

    【解决方案2】:

    您似乎正在尝试从已知集合中随机选择不重复的数字,例如在彩票中所做的那样。如果集合不是太大,这种方法会起作用(请注意,如果计数大于数字的数量,它将失败)。

    /** Will pick `count` numbers randomly from the set of numbers between
     * startNumber (included) and endNumber (excluded). */
    public static Collection<Integer> randomPick(int startNumber, int endNumber, int count) {
        // Generate a list of all numbers from start to endNumber
        List<Integer> numbers = new ArrayList<Integer>();
        for(int i = startNumber; i < endNumber; i++) {
            numbers.add(i);
        }
    
        // Shuffle them
        Collections.shuffle(numbers);
    
        // Pick count items.
        return numbers.subList(0, count);
    }
    

    【讨论】:

    • 您应该使用Set 而不是List
    • 你不能在 Set 上使用 Collections.shuffle。
    • 抱歉,您的评论没有意义。您将如何从 Set 中检索元素的随机子集?
    • Collections.shuffle 无论如何只需要一个 List 作为参数;在 Set 上没有意义。
    • @AmirPashazadeh:这有什么关系?在自然数的情况下,TreeSet 中的顺序将是元素的自然顺序,然后您必须手动编写自己的 shuffle 例程。据我所知,HashSet 还会为您提供自然排序,或者充其量是非自然但仍可预测的排序,而不是随机排序。
    【解决方案3】:

    你的问题是你总是使用相同的种子,所以生成相同数字的机会非常高,首先你需要了解生成纯随机数是不可能的,Java给你的是一个漂亮的不错的机制,但依赖于种子。

    一种常见的做法是以毫秒为单位使用当前日期时间,因此,如果您这样做:

    new Random(System.currentTimeMillis())
    

    你会发现你没有得到重复。您可以使用以下代码进行尝试:

    public static void main (String... args){
       for (int i=0; i<10000; i++){
           try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
           Random random = new Random(System.currentTimeMillis());
           System.out.println(random.nextInt());
    
       }
    }
    

    【讨论】:

    • 这仍然会产生重复,只是顺序不同
    • 嗨 Jarrod,感谢您在评论中重复我在回答中所说的话!真是好搭档!所以告诉我们......你有真正的随机发生器的解决方案吗?也许你可以为此赢得新奖!显然,这不会产生唯一的数字列表,但我很确定我会运行相当长的时间,然后才会产生重复......几乎只是基于从调用到调用经过一些毫秒的假设。 ..
    • 只需使用 Thread.sleep(100) 在 10000 次重复循环中运行它,你猜怎么着,甚至没有一个重复...
    • 一个“真实的”随机数生成器会根据设计发出重复项,Java 提供的随机数生成器没有任何不真实或错误的地方。一组随机生成的唯一数字是另一回事。
    【解决方案4】:

    如果您创建和初始化(使用种子)一次 Random 对象会更好,而不是在每次调用您的 Listener 时创建随机对象,这样就不太可能有重复的数字。

    【讨论】:

      【解决方案5】:
      import java.util.Set;
      
      Set<Integer> mySet = new HashSet<Integer>(10); // do you know how many elements do you need?
      boolean elementNotThere;
      do {
          int myInt = r.nextInt(hoogste + 1 - laagste);
          elementNotThere = mySet.add(myInt);
      } while ( ! elementNotThere );
      

      【讨论】:

      • @JarrodRoberson 没有尝试过,可能有几个或错字,但我不同意 -1
      • @JarrodRoberson 我感谢 yatskevich 和我自己。不是你没有建设性。
      • 它仍然没有任何意义:它只是在到达重复元素时停止,这意味着元素太少或太多。布尔值的名称表明它的实际作用相反。
      • @toto2 不,它会继续生成随机数,直到它可以插入集合中。关于变量的名称,我已经更改了。
      • @vulkanino 如果add 因为重复而失败,elementExists 被设置为 false 并且你退出循环。
      猜你喜欢
      • 2017-06-06
      • 1970-01-01
      • 1970-01-01
      • 2016-07-03
      • 2010-12-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多