在Java中生成不相等的随机数对p和q。

4
我试图创建在范围[0,n)内的随机整数对。 我需要确保对于任何输入n,所创建的数字p和q不相等,即p != q
我尝试使用具有种子的java.util.Random,以便能够再现结果。我尝试了100,200,400,800的输入,它们都产生了不同的p和q,使得p != q。但是在1600时,两个对满足p == q
public static void generate(int size){      
    Random ran = new Random();
    ran.setSeed(123456L);       
    for(int i =0;i<size;i++){
        int p = ran.nextInt(size);
        int q = ran.nextInt(size);
        if(p==q)
            System.out.println(p+" equals "+q);
        //else
            //System.out.println(p+" "+q);
    }
}

public static void main(String[] args) {
    generate(1600);

}

这提供了。
692 equals 692
843 equals 843

我确定有一种方法可以确保对于任何输入n,p != q.. 但是我无法回忆起所需的数学知识。有人能帮忙吗?

3
你需要一颗不会生成连续相等值的种子吗?你可以检查 pq 是否相等,如果相等则重新生成一个随机值。 - acdcjunior
如果你生成的随机数是奇数,则有一种可能性:始终选择 max - generatedNumber,它将始终给出不同的结果。也就是说,如果数字从1开始而不是0。 - fge
好吧...并不是对于任何 n。如果 n 是0,它们将总是匹配的。 :) 此外,注意声明这样的种子。您的程序现在将每次都给出相同的结果。 - asteri
3
你希望生成这样的一组随机数对吗?我不确定提议的方法是否能够做到这一点。直觉上,创建两个数字并在它们相等时拒绝这一对似乎更为可靠。 - George
4个回答

6

一直选择,直到它们不匹配为止。

int p = ran.nextInt(size);
int q;

do {
    q = ran.nextInt(size);
} while(p==q);

7
你可以在 p 等于 q 的时候执行 {...}。 - Erwin Smout

4

生成一个在[0,n)范围内的数字和另一个在[0,n-1)范围内的数字。 如果第二个数字大于等于第一个数字,则将第二个数字加一。

int p = ran.nextInt(size);
int q = ran.nextInt(size-1);

if (q>=p){
    q++;
}

我认为手动递增/递减数字使其成为计算的,而不是随机的。但我想这是一个哲学观点。 - asteri
1
避免其他解决方案可能出现的Θ(∞)运行时间,这是一个加分项。(实际上几乎不重要,但无论如何。) - Imre Kerr
q是随机的,增量只是为了确保最终结果覆盖区间[0,n)。 - Guillaume
即使它有硬件随机数生成器,其结果也必须进行转换才能进入nextInt调用所需的特定范围。这只是同一过程中的另一步骤。 - Patricia Shanahan
1
它稍微不那么均匀,即q-p==1的概率现在是q-p==2的两倍。 - GeertPt
显示剩余3条评论

1

其中一种解决方案如下:

  1. 生成第一个数字
  2. 生成第二个数字
  3. 当第二个数字等于第一个数字时,返回步骤2

在几乎100%的情况下,步骤2不会执行超过两次。

但请确保n大于1,否则会进入无限循环(但无论如何,使用任何算法都无法得到正确的结果)


1
在一个列表中加1到n。然后使用Collection.Shuffle来随机整个列表。它将以相等的可能性洗牌列表。然后从列表中获取任意2个。
例如:
ArrayList a = new ArrayList();
for(int i = 1;i <= n; i++)
    a.add(i);
Collections.shuffle(a);
int first = (int)a.get(0);
int second = (int)a.get(1);

2
这是一个好主意,因为它确保“生成”两个数字本身,而不仅仅是获取两个数字并进行比较。+1。 - asteri
洗牌整个列表是浪费的。只需将第一个元素与随机元素交换,第二个元素与随机元素交换即可。(洗牌正是这样做的,只不过是对整个列表进行操作。请参见https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle。) - Imre Kerr
然而,您应该知道,您的示例不能编译。ArrayList包含Object,这些对象无法转换为int。您应该将它们转换为Integer并依赖于自动拆箱。 - asteri
@jeff 真的吗??只需编译检查一下,你就会看到魔法:p - stinepike
1
@StinePike 真的。除非我的Eclipse在骗我。哈哈。http://imgur.com/IPvyE6C - asteri
@Jeff,你用的是哪个JDK?这段代码在我的Eclipse中可以运行。我正在使用1.7版本。 - stinepike

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