这是我最近参加的一次访谈中提出的问题。
据我所知,可以按如下方式生成两个数字之间的随机数
public static int rand(int low, int high) {
return low + (int)(Math.random() * (high - low + 1));
}
但是我在这里使用Math.random()来生成0到1之间的随机数,并使用它来帮助我在低和高之间生成。有没有其他方法可以直接使用外部函数?
答案 0 :(得分:37)
典型的伪随机数生成器根据以前的数据计算新数字,因此理论上它们是完全确定的。通过提供良好的种子(随机数生成算法的初始化)来保证唯一的随机性。只要随机数不是非常安全关键(这需要“实际”随机数),这种递归随机数生成器通常可以满足需求。
一旦提供种子,递归生成可以在没有任何“外部”功能的情况下表达。有几种算法可以解决这个问题。一个很好的例子是Linear Congruential Generator。
伪代码实现可能如下所示:
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;
}
您仍然需要为此生成器添加一些初始值。这可以通过执行以下操作之一来完成:
请注意,无算法可为不同运行相同输入生成不同的值访问一些外部源,如系统环境。每个种子播种的随机数生成器都使用一些外部源。
答案 1 :(得分:7)
在这里,我建议一些评论来源可能对您有所帮助:
/proc
文件数据:在Linux系统上。我觉得你应该用这个。
/proc/sys/kernel/random:
该目录包含控制文件/dev/random
的操作的各种参数。
字符特殊文件/dev/random
和/dev/urandom
(自Linux
1.3.30
以来出现)提供了内核随机数生成器的接口。
试试这个逗号:
$cat /dev/urandom
和
$cat /dev/random
您可以编写从此文件读取的文件读取功能。
`
答案 2 :(得分:5)
System.currentTimeMillis()
是否算作外部?你总是可以得到这个并用一些最大值来计算mod:
int rand = (int)(System.currentTimeMillis()%high)+low;
答案 3 :(得分:1)
您可以使用变量的地址或组合更多变量的地址来制作更复杂的变量......
答案 4 :(得分:1)
你可以从x = 4x(1-x)
和{{1}之间的“非理性”x
开始,从逻辑地图0
获得接近随机性(实际上是混乱的,绝对不是统一的*) }。
“随机性”出现,因为浮点表示精度边缘的舍入误差。
(*)一旦你知道它存在,你可以撤消倾斜。
答案 5 :(得分:0)
您可以获得当前的系统时间,但这也需要大多数语言的功能。
答案 6 :(得分:0)
如果允许使用某些外部状态(例如,使用当前系统时间初始化的长时间),则可以在没有外部函数的情况下执行此操作。这足以让您实现一个简单的伪随机数生成器。
在对随机函数的每次调用中,您将使用state创建新的随机值,并更新状态,以便后续调用获得不同的结果。
您只需使用常规Java算法和/或按位运算即可完成此操作,因此无需外部函数。
答案 7 :(得分:0)
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++;
}
}
}
}
答案 8 :(得分:-2)
泊松随机生成器
让我们假设我们从随机数的期望值“v”开始。然后说一系列非负整数满足具有期望值v的泊松分布意味着在子序列上,该值的平均值(平均值)将显示为“v”。 泊松分布是统计数据的一部分,细节可以在维基百科上找到。 但是这里使用这个功能的主要优点是: 1.仅生成整数值。 2.这些整数的平均值将等于我们最初提供的值。
在小数值没有意义的应用程序中很有用。就像1分钟到达机场的飞机数量是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将达到目的。 我们应该使用哪种功能完全取决于应用程序。