生成唯一的随机整数集合。

3

这是我第一次构建应用程序,遇到了一个问题。我正在制作一个会生成随机数字的应用程序,但有时候它会显示相同的数字两次。这不是我的目标,所以我该如何编程使其显示不重复的随机数字?

顺便说一下,这是我的代码:

    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);


              }

            });
        }
    }

1
随机数是随机的,可能会生成相同的数字超过一次。你可以在循环中生成这些数字并将它们分配给一个Set,这将确保你不会有重复的数字。 - vulkanino
我们谈论的数字有多少个? - stryba
没有确切的随机数数量。使用该应用程序的人可以在aantalT中指定他或她想要多少个随机数。我尝试了这个: ArrayList<Integer> dubbel=new ArrayList<Integer>(); for(int i = 0; i < aantal; i++) { aNumber = laagste + r.nextInt(hoogste + 1 - laagste); while (dubbel.contains(aNumber)){ aNumber = r.nextInt(hoogste + 1 - laagste); } build += aNumber + "\n";只是它不起作用。 - Kelzaaa
ARRG的解决方案和我的都能够满足你的需求。 - toto2
5个回答

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算法,但只适用于少量元素。


0
您的问题在于始终使用相同的种子,因此生成相同数字的可能性非常高,首先需要理解的是不可能生成纯随机数,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());

   }
}

2
这个将会产生重复的项,只是顺序不同。 - user177800
嗨,Jarrod,感谢您在评论中重复了我在答案中所说的内容!太好了,伙计!那么告诉我们...您有真正随机生成器的解决方案吗?也许你可以因此赢得诺贝尔奖!显然,这不会产生一个唯一的数字列表,但我相信在它产生重复之前,它会运行相当长的时间......几乎只基于这样的假设:从调用到调用需要一些毫秒的时间...... - Alberto Gutierrez
刚刚用10000次重复循环和Thread.sleep(100)运行了它,猜猜看,竟然没有一个重复的... - Alberto Gutierrez
1
一个“真正”的随机数生成器会通过设计发出重复的数字,Java提供的随机数生成器没有不真实或错误之处。而随机生成一组唯一的数字则是另外一回事。 - user177800

0

看起来你正在尝试从已知集合中随机选择不重复的数字,就像在彩票中一样。这种方法是可行的,前提是集合不太大(请注意,如果计数大于数字数量,则会失败)。

/** 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);
}

1
你应该使用 Set 而不是 List - user177800
1
你不能在 Set 上使用 Collections.shuffle。 - ARRG
1
抱歉,您的评论没有意义。如何从Set中检索随机子集? - ARRG
1
Collections.shuffle只接受List作为参数;在Set上使用它是没有意义的。 - toto2
1
@AmirPashazadeh:这与什么相关呢?对于自然数,TreeSet中的顺序将是元素的自然排序,然后您将不得不手动编写自己的洗牌程序。据我所知,HashSet也会给您提供自然排序,或者至少是一种非自然但仍可预测的排序,而不是随机的。 - ARRG
显示剩余8条评论

0
最好只创建和初始化(使用种子)一次Random对象,而不是在每次调用Listener时都创建随机数,这样重复的数字就会更少。

-2
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。 - vulkanino
@JarrodRoberson,我感谢yatskevich和我自己。并不是你在做出建设性的贡献。 - vulkanino
它仍然没有意义:当它到达重复元素时,它只会停止,这将意味着元素太少或太多。而布尔值的名称表示了与其实际功能相反的含义。 - toto2
@toto2 不,它会持续生成随机数,直到可以插入集合中。至于变量名,我已经更改了。 - vulkanino
@vulkanino 还是不行:你加了一个数字,elementExists 就被设置为 true,然后你就跳出了循环。 - toto2
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接