Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 不使用任何外部函数生成随机数_Java_C++_C_Algorithm_Data Structures - Fatal编程技术网

Java 不使用任何外部函数生成随机数

Java 不使用任何外部函数生成随机数,java,c++,c,algorithm,data-structures,Java,C++,C,Algorithm,Data Structures,这是我最近参加的一次采访中提出的问题 据我所知,两个数字之间的随机数可以如下生成 public static int rand(int low, int high) { return low + (int)(Math.random() * (high - low + 1)); } 但在这里,我使用Math.random()生成一个介于0和1之间的随机数,并使用它来帮助我生成介于低和高之间的随机数。有没有其他方法可以不使用外部函数直接执行?您可以使用一个变量的地址,或者将更多变量的地址组

这是我最近参加的一次采访中提出的问题

据我所知,两个数字之间的随机数可以如下生成

public static int rand(int low, int high) {
    return low + (int)(Math.random() * (high - low + 1));
}

但在这里,我使用Math.random()生成一个介于0和1之间的随机数,并使用它来帮助我生成介于低和高之间的随机数。有没有其他方法可以不使用外部函数直接执行?

您可以使用一个变量的地址,或者将更多变量的地址组合成一个更复杂的地址…

您可以获得当前的系统时间,但在大多数语言中,这也需要一个函数。

典型的伪随机数生成器根据以前的数字计算新的数字,因此理论上它们是完全确定的。唯一的随机性是通过提供良好的种子(随机数生成算法的初始化)来保证的。只要随机数不是非常安全关键的(这需要“实”随机数),这样的递归随机数生成器通常就能满足需要

一旦提供了种子,递归生成就可以在没有任何“外部”函数的情况下进行表示。有两种算法可以解决这个问题。一个很好的例子是

伪代码实现可能如下所示:

long a = 25214903917;   // These Values for a and c are the actual values found
long c = 11;            // in the implementation of java.util.Random(), see link
long previous = 0;

void rseed(long seed) {
    previous = seed;
}

long rand() {
    long r = a * previous + c;
    // Note: typically, one chooses only a couple of bits of this value, see link
    previous = r;
    return r;
}
您仍然需要为这个生成器添加一些初始值。这可以通过执行以下操作之一来完成:

long a = 25214903917;   // These Values for a and c are the actual values found
long c = 11;            // in the implementation of java.util.Random(), see link
long previous = 0;

void rseed(long seed) {
    previous = seed;
}

long rand() {
    long r = a * previous + c;
    // Note: typically, one chooses only a couple of bits of this value, see link
    previous = r;
    return r;
}
  • 使用类似于当前时间的内容(在大多数非安全关键情况下,如游戏中,效果良好)
  • 使用硬件噪声(有利于安全关键随机性)
  • 使用一个常量(有利于调试,因为您总是得到相同的序列)
  • 如果你不能使用任何函数,也不想使用一个常量种子,如果你使用的是一种允许这样做的语言,你也可以使用一些未初始化的内存。例如,在C和C++中,定义一个新变量,不要给它指派一些东西,并用它的值来生成生成器。但请注意,这远远不是一个“好种子”,只是一个黑客来满足您的要求。永远不要在真实代码中使用此选项

请注意,没有算法,该算法可以使用相同的输入为不同的运行生成不同的值,而无需访问一些外部源,如系统环境。每个种子良好的随机数生成器都会使用一些外部源。

System.currentTimeMillis()是否算作外部源?您始终可以获得该值,并通过某个最大值计算mod:

int rand = (int)(System.currentTimeMillis()%high)+low;

如果允许您使用某些外部状态(例如,使用当前系统时间进行长时间初始化),则您可以在不使用外部功能的情况下执行此操作。这足以让您实现一个简单的psuedo随机数生成器

在对随机函数的每次调用中,您将使用状态创建新的随机值,并更新状态,以便后续调用得到不同的结果


您只需使用常规Java算术和/或按位操作即可实现这一点,因此不需要外部函数。

这里我建议您使用一些带有注释的源代码,您可能会发现它们很有用:

  • 系统时间:一天中单调随机。快,容易
  • 鼠标点:随机但在独立系统上不有用
  • 原始套接字/本地网络 (数据包的信息部分):良好的随机技术和耗时-可以模拟攻击模式以减少随机性
  • 一些带有排列的输入文本:快速、通用,也很好(在我看来)
  • 由于键盘、磁盘驱动器和其他事件导致的中断计时:常见方式–如果不小心使用,则容易出错
  • 另一种方法是提供模拟噪声信号:例如temp
  • /proc
    文件数据:在Linux系统上。我觉得你应该用这个

    /proc/sys/kernel/random:
    此目录包含控制文件操作的各种参数
    /dev/random

    字符特殊文件
    /dev/random
    /dev/uradom
    (从
    Linux开始出现)
    1.3.30
    )提供内核随机数生成器的接口

    试试这个命令:

    $cat /dev/urandom   
    

    $cat /dev/random
    
    您可以编写一个从该文件读取的文件读取函数

    阅读(也建议):


`

从逻辑图
x=4x(1-x)
开始,从
0
1
之间的一个“非理性”
x
开始,你可以得到近似随机性(实际上是混沌的,绝对不是均匀的*)

出现“随机性”是因为浮点表示精度边缘的舍入误差


(*)一旦知道存在倾斜,就可以撤消倾斜。

泊松随机生成器

假设我们从随机数的期望值“v”开始。然后说一个非负整数序列满足泊松分布,期望值为v,这意味着在子序列上,该值的平均值将出现“v”。 泊松分布是统计数据的一部分,详细信息可以在维基百科上找到。 但在这里,使用此功能的主要优点是: 1.只生成整数值。 2.这些整数的平均值将等于我们最初提供的值

在分数值没有意义的应用中,它很有用。同样,一分钟内抵达机场的飞机数量为2.5架(没有意义),但这意味着2分钟内有5架飞机抵达

int poissonRandom(double expectedValue) {
  int n = 0; //counter of iteration
  double limit; 
  double x;  //pseudo random number
  limit = exp(-expectedValue);
  x = rand() / INT_MAX; 
  while (x > limit) {
    n++;
    x *= rand() / INT_MAX;
  }
  return n;
}
线路

rand() / INT_MAX
应生成一个介于0和1之间的随机数。所以我们可以利用系统的时间。 秒/60将达到此目的。 我们应该使用哪个函数完全取决于应用程序。

公共类randomNumberGenerator{
public class randomNumberGenerator {

    int generateRandomNumber(int min, int max) {
        return (int) ((System.currentTimeMillis() % max) + min);
    }

    public static void main(String[] args) {
        randomNumberGenerator rn = new randomNumberGenerator();
        int cv = 0;
        int min = 1, max = 4;
        Map<Integer, Integer> hmap = new HashMap<Integer, Integer>();

        int count = min;
        while (count <= max) {
            cv = rn.generateRandomNumber(min, max);
            if ((hmap.get(cv) == null) && cv >= min && cv <= max) {
                System.out.print(cv + ",");
                hmap.put(cv, 1);
                count++;
            }
        }

    }
}
int GeneratorDomainNumber(int最小值,int最大值){