我正在尝试生成0到59的随机数,并且对C中的rand()函数不满意。这是我正在使用的代码:
#include #include main() { int num; srand(time(NULL)); num = rand(); num = num % 59; printf("%dn", num); }
我已经重复了这段代码的运行,并注意到生成的随机数似乎并不是随机的。 生成的数字肯定是遵循一种模式,因为每次运行程序时,数字会逐渐变大,直到它回绕到开头(即2,17,21,29,38,47,54,59,4, 11 ….等)。
有没有一种方法可以使函数播种,这样每次重新运行函数时,我得到一个真正的随机数,生成的概率为1/60? 或者是否有任何替代方法我可以自己实现而不是在C中使用rand()函数?
有没有一种方法可以使函数播种,这样每次重新运行函数时,我都会获得一个真正的随机数
不,C标准库使用PRNG(伪随机数生成器)。 你永远不会得到真正的随机数。
但是,您可以使用比time()
更频繁更改的内容来播种它,例如,在POSIX上:
struct timeval tm; gettimeofday(&tm, NULL); srandom(tm.tv_sec + tm.tv_usec * 1000000ul);
此外,使用模运算符生成随机数不是一个好的解决方案(它会严重降低熵)。 如果您有BSD样式的libc实现,请使用
uint32_t n = arc4random_uniform(60);
或者,如果您没有此function:
// random() is guaranteed to return a number in the range [0 ... 2 ** 31) #define MAX_RANDOM ((1 << 31) - 1) long n; do { n = random(); } while (n > (MAX_RANDOM - ((MAX_RANDOM % 60) + 1) % 60)); n %= 60;
注意使用random()
– 它优于rand()
(它有许多低质量的实现)。 可以使用srandom()
播种此函数。
或者是否有任何替代方法我可以自己实现而不是在C中使用rand()函数?
你当然可以(当然,C库实现的编写者会怎么做呢?),但你最好不要 – 这是一个单独的科学来写一个好的PRNG,所以说。
编写程序的方式,每次都必须重新运行它以获得一个新的随机数,这也意味着每次都重新播种。 重新种植PRNG是不好的 。
你想种子一次 ,然后生成一堆随机数。
这样做:
int main(void) { int num, i; srand(time(NULL)); // Seed ONCE for(i=0; i<100; ++i) // Loop 100 times for random numbers { num = rand(); num = num % 59; printf("%dn", num); } }
现在你应该得到更好的结果。
每次重新运行程序时,都会使用time()
重新播种,并且该函数每秒只会前进一次(如果您足够快地重新运行程序,则会获得相同的结果)。
它似乎在它翻转之前递增的事实表明对rand()
的第一次调用返回未修改的种子 – 该数字每秒递增一次。 在这种情况下,您将获得与运行时相同的结果(或非常相似的结果):
printf("%dn", time(NULL) % 59);
我相信你可以看出它有什么问题。
在这种情况下,如果你使用’更正确’的rand() * 59 / RAND_MAX
,这意味着更喜欢“更随机”位的值,你会有更糟糕的情况 – 结果不会改变总共可能持续500秒或更长时间。
从根本上说,你需要找到一个不太可预测的种子,但你可能还希望在使用它之前看到它已正确混合。
从/dev/urandom
读取应该提供一个好的种子,在这种情况下你不需要担心混合,但是否则多次调用rand()
应该有助于消除低质量的特别明显的文物你开始的种子(当然,除了它每秒只改变一次的问题)。
以上就是c/c++开发分享C中的随机数发生器相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/562652.html