如何生成不会立即重复的准随机数(以及更多)?

时间:2017-07-16 23:56:15

标签: java random

我想为以下规范生成一系列无穷无尽的准随机数: -

  • 数字来源均匀分布且随机,范围为0到255(含)。它是现有的硬件设备。
  • 所需的输出范围为1到8,包括在内。
  • 两个连续的输出数字永远不会相同。例如5永远不会跟随5,但你可以有5,2,5。
  • 每个源数需要一个输出数。因此不能使用拒绝取样。而while()循环,shuffle等不能使用。

这是令我烦恼的最后一条规定。源生成器只能以1 / s的常数提供随机字节,我希望以1 / s的常数输出。通常,如果生成的数字等于前一个数字,则只需拒绝生成的数字,然后生成另一个数字。在我的情况下,每次输出只能获得一次。我认为这是某种随机选择过程,但是由于我是一个糟糕的程序员,这个要求让我绕圈子走了。算法,流程图或图片都可以,但我将用Java实现。

为半通用标题道歉,但我真的想不出任何更准确而简洁的内容。

2 个答案:

答案 0 :(得分:1)

如果我正确理解了问题,将从8个不同的数字(1到8)中随机选择第一个随机数,而每个连续的随机数将从7种不同的可能性中选择(1到8除了前一个) 。因此,您需要将256个值的范围分为7种可能性。它甚至不会出来,但这是你能做的最好的。所以你需要像

这样的东西
public class RandomClass {
    public RandomClass(HardwareSource source) {
        this.source = source;
        first = true;
    }
    pubic int nextRandom() {
        int sourceValue = source.read();
        int value;
        if (first) {
            value = sourceValue % 8 + 1;
            prev = value;
        } else {
            value = sourceValue % 7 + 1;
            if (value >= prev) {
                value++;
            }
        prev = value;
        first = false;
        return value;
    }
}

假设第一次调用生成5.第二次调用它时,value首先被计算为1到7之间的数字;如果值>> 5则通过递增它,可能输出的范围变为1,2,3,4,6,7,8。输出将几乎均匀地分布在这两个值之间。由于256不能被7整除,因此分布不均匀,并且对较低的数字会略有偏差。你可以修复它,以便偏差在每次调用时都会移动,甚至在整个序列中都会偏移;我相信一种方式是

 value = (sourceValue + countGenerated) % 7 + 1;

您可以跟踪自己生成的数量。

我认为这比采用模8的输入更好,如果数等于前一个,则加1。这些解决方案将生成prev + 1,生成其他数字的概率是其两倍,因此它的偏差比必要的更多。

答案 1 :(得分:0)

int sum=0;
int prev=-1;
int next(int input){
  sum=(sum+input)%8;
  if(sum==prev)sum=(sum+1)%8;
  prev=sum;
  return sum+1;
}

(正如我解释的那样,即使使用新的大胆强调,也不需要总是为相同的输入值生成相同的输出值 - 这将使任务无法解决)