我在一个编码环境中,我只能访问一些最基本的 c 函数。#include'ing 其他库是不可行的。
在这种环境中,我可以调用 rand() ,它在我的环境中给我一个介于 0 到 32767 之间的随机数(我认为)。下面的代码是否是正确的逻辑来获得一个像 rand() 一样均匀分布的更大的随机数?
rnum = rand() * (32767 + 1) + rand();
rnum = (rand() << 15) | rand()
might be faster, but if you need good quality random numbers you should look for an external library. Built-in random functions are generally adequate only for the simplest applications.
static unsigned long next = 1;
int my_rand(void) {
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % (RAND_MAX+1));
}
void my_srand(unsigned int seed) {
next = seed;
}
在 Linux 上
#define RAND_MAX 2147483647
您的环境 RAND_MAX 可能是 32767
参考:http ://en.wikipedia.org/wiki/Linear_congruential_generator
如果您没有内存限制,您还可以查看http://en.wikipedia.org/wiki/Mersenne_twister代码是可嵌入的,就像上面的示例一样
在将任何随机数生成器用于重要用途之前,应对其进行广泛测试。这是有关此主题的一篇文章的链接。
关于真实随机数的弱点的有趣背景可以在二战布莱切利公园的密码破解者的各种历史中找到。在战争的大部分时间里,德国人和希特勒都认为他们的密码是牢不可破的,因为他们用随机数加密,而英国人在几个月内就完全破解了所有这些密码,因为德国人在实施“随机性”方面存在各种弱点。许多代码在几天或几个月内被充分“扭曲”,即使没有彻底破坏,即使没有完全破坏,也足以使用。
除了这里提出的其他优秀解决方案之外,您还可以在 RAND_MAX 中进行幂扩展,在用户定义的 MY_RAND_MAX 处截断,并丢弃会导致一致性被破坏的解决方案。
int myrand(int MY_RAND_MAX)
{
int j = 0, num = 0;
// Generate digits for expansion in powers of RAND_MAX, up to acceptable range.
while (pow(RAND_MAX + 1, j) <= MY_RAND_MAX){
num = num + rand() * (int)pow(RAND_MAX + 1, j);
j++;
}
//compute remainder to determine truncation
int remainder = ((int)pow(RAND_MAX + 1, j)) % (MY_RAND_MAX + 1);
// If number is within accepted bounds, mod and return
if (num <= ( (int)pow(RAND_MAX + 1, j) - remainder ) ){
return (num % (MY_RAND_MAX + 1));
// Else, if number generated exceeds allowed bounds, rerun method.
}else if (num > ( (int)pow(RAND_MAX + 1, j) - remainder ) ){
return myrand(MY_RAND_MAX);
}else{
exit(-1);
}
}
您可以凭经验检查此方法是否在给定范围内为您提供了统计上一致的输出。
我已经对不同范围的几次试验进行了此操作,每个试验的样本量为 100000,并且在样本方差和预期方差至少为 3 sig 之间达成了一致。无花果每次。
ps 我不是编码员,而是最近学习编码的数学家/物理学家,因此我们将不胜感激对我的代码质量的任何和所有反馈。