Java中随机生成器的问题

Problem with random generator in Java

我正在做一个无线项目,这个项目涉及模拟802.11 MAC协议。我在里面使用了随机生成器,问题是我们得到的图形是不平滑的,我相信这个bug是因为随机生成器。为了测试,我运行了下面的代码,它生成了100个介于0和19之间的随机数。如果仔细观察输出,有几个连续的数字是相同的或非常接近的(例如17、15、16…或者1,1,…)。它会导致在我们的模拟中发生碰撞,并且相应的吞吐量会在该点下降(即,蠕动形状)。在这种情况下,增加模拟运行时间并没有多大帮助。

谁能帮我弄清楚如何在Java中生成一个随机的随机数(没有这种模式)?

这是要尝试的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.Random;

public class RandomTest {

    public static void main(String[] args){

        int [] counter = new int [20];

        Random generator = new Random();
        int randomIndex = 0;

        for (int i=0; i<100; i++){

            randomIndex = generator.nextInt(20);
            counter[randomIndex]++;
            System.out.println(randomIndex);
        }
    }
}

随机并不意味着每次都不同。偶尔会出现重复或类似的值,特别是当您从如此小的范围(20个值)中选择数字时。

如果你真的希望每个数字都不同于前面的数字,那么你必须自己编程。最简单的方法之一(但不是最有效的方法)是拒绝一个在前一个随机数的距离x内的随机数,然后选择另一个数字-重复,直到得到一个你满意的数字。


避免重复的最简单方法是使用collections.shuffle()。

1
2
3
List<Integer> ints = new ArrayList<Integer>();
for(int i=0;i<20;i++) ints.add(i);
Collections.shuffle(ints);

同样,如果您希望值0-19精确显示5次,您可以这样做。

1
for(int i=0;i<100;i++) ints.add(i/5);


我不能说你的结果是否正常。但是如果你对java.util.Random不满意,那就看看java.security.SecureRandom吧。


我觉得你的算法有点奇怪。你创建了20个int,然后随机增加一个,重复100次?你为什么不这样做:

1
2
3
4
5
6
7
public static int[] randomNumbers(int n, int max) {
    Random r = new Random();
    int[] rndNums = new int[n];
    for (int i = 0; i < n; i++)
        rndNums[i] = r.nextInt(max);
    return rndNums;
}

这是一种避免重复的方法…(对于n较大且接近最大值的情况,有更有效的解决方案)

1
2
3
4
5
6
7
8
9
10
11
public static int[] randomNumbers(int n, int max) {
    Random r = new Random();
    Set<Integer> taken = new HashSet<Integer>();
    int[] arr = new int[n];
    for (int rnd, i = 0; i < n; i++) {
        while (!taken.add(rnd = r.nextInt(max)));
        arr[i] = rnd;
    }

    return arr;
}

另外,请注意,Random提供的数字是伪随机的。检查真正的随机生成在Java中的"真正"的随机性。


随机产生的psudo随机性非常接近于真实的随机性。我认为问题背后的问题在于,不了解真实的随机性,也可能不了解模拟所针对的无线问题的统计性质。好的。

在使用random从0-19中获取整数时,我们可以期望得到以下结果。在任何特定时间获得任何特定数字的概率是1:20,并且不依赖于任何以前的数字。这是随机性的一个基本特性。因此,下一个数字与刚获得的数字匹配的概率是1:20。这意味着,平均而言,同一行中的两个数字每随机获得一个数字的20倍中就有1个出现。这只是平均水平。从统计学上讲,这种情况会发生在泊松分布中。有时配对会发生两次或更多。其他情况下,对于长序列的数字不会发生这种情况。好的。

这个问题指出,问题不仅是同一行中的同一个数字,而且值太接近的数字也是一个问题。假设一个随机数生成器不会连续两次生成同一个数,它绝对不是随机的,它有明显的偏差,根本不像随机性。一个假设的随机数生成器,如果它不能产生比某个预定值更接近的连续数,那么它的偏差甚至比一个连续不产生相同数的生成器更大。好的。

如果802.11 MAC吞吐量失败,或者由于随机数相同或值太接近而出现波动且不平滑的图形,那么更有用的问题可能是无线设计中的缺陷还是模型中的缺陷?好的。

答案的后一部分是基于可以从问题的稀疏细节中收集到的信息,特别是当它描述802.11 MAC传输冲突、随机碰撞后重新传输等待时间、传输检测延迟和最终吞吐量故障等方面时。好的。

随机分配碰撞发射器等待时间增量的rand对象将精确地给出分析碰撞行为所需的近似随机性。在这一层次上的分析可能并不顺利,因为802.11mac站的随机行为的真实性质,它是摇摆不定的。如果由于使用这种随机性的冲突问题导致模型中出现吞吐量故障,那么在模型或802.11 MAC设计中很可能存在其他困难。此时,讨论与碰撞有关的基本802.11mac操作可能很有用。好的。

在802.11 MAC操作中,两个试图同时传输的站是一种常见的情况,通常是指碰撞。两个站点都不能使用通信信道。信道使用水平,或者更确切地说,尝试使用会导致所谓的拥塞失败。用于此类故障的策略称为CSMA/CD,即载波检测、多重访问/碰撞检测。有一些QoS(服务质量)的复杂性可以添加到CSMA/CD中以进一步增强冲突避免,但我不会在这里描述它们。好的。

CSMA/CD描述如下。电台在发射前先收听,只有在另一个电台不发射时才开始发射。发射台检测另一个发射台是否与之碰撞。如果检测到碰撞,则传输站将停止传输,并在重新尝试传输之前等待一段随机时间。碰撞发生的原因是延迟时间总是存在于任何两个发射器之间,因此两个性能良好的发射器始终可能发生碰撞。好的。

延迟时间有两个贡献者。第一种是传输介质将信号从一个发送器传送到另一个发送器所需的时间。第二个是一个发送器需要的时间,一旦它检测到没有其他的站正在传输,开始自己的传输。总延迟同时影响所有可能的发射机。另一种常见的情况是两个站点随机等待相同的时间再次尝试传输,在这种情况下,如果其他一些站点尚未开始传输,并且检测到该传输,则它们将再次碰撞并继续碰撞,直到其中一个站等待的等待时间与另一个站的等待时间完全不同为止。不会再发生碰撞。好的。

如果有太多的站点同时尝试传输,然后随机等待尝试重新传输,就会出现一种称为拥塞故障的情况。随机等待时间必须比等待时间长,以使所有不同的等待时间都足够不同,以便一个在尝试重新传输之前能够感知另一个的载波。例如,等待时间增量是延迟时间长度的一半,将有效的可用等待时间池减少一半。因此,等待时间增量小于延迟时间毫无意义。此外,可供选择的等待时间池应具有足够的值范围,等待时间冲突很少发生。好的。

我希望这能澄清几个问题——随机性、随机序列的性质以及802.11 MAC类型网络中冲突的性质。好的。好啊.


"随机"并不意味着"均匀分布",一个真正的随机序列实际上会偶尔出现类似数字的聚集,或者重复相同的数字几次。如果你连续三次掷骰子,你不是偶尔一次掷三次吗?

你到底想让发行版看起来像什么?您可以使用一个渐进序列,并用一个随机值修改序列返回的数字。这样你就可以得到一个有随机干扰的形状结果。


在0到19的范围内,100个样本几乎肯定会得到一些连续值重复或接近重复。如果你想所有的数字至少分开K,你可以尝试这样的方法。

1
randomIndex = (randomIndex + k + generator.nextInt(20 -2*k) % 20;

范围中的-2*k是为了防止添加的随机量"环绕"到当前值的k单位内。

请注意,严格地说,通过这种方式获得的值并不像RNG中的原始值那样随机,但听起来纯粹的随机性并不是您想要的。


不能保证随机数序列不会有重复;事实上,对于您正在使用的小范围,它很可能…真正的问题(数学家也有其他问题):这些值是否均匀地分布在一个长序列上?


http://en.wikipedia.org/wiki/cryptography_secure_pseudorandom_number_generator